2005-11-15 Robert McQueen <robot101@debian.org>
[platform/upstream/dbus.git] / bus / driver.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  *
23  */
24
25 #include "activation.h"
26 #include "connection.h"
27 #include "driver.h"
28 #include "dispatch.h"
29 #include "services.h"
30 #include "selinux.h"
31 #include "signals.h"
32 #include "utils.h"
33 #include <dbus/dbus-string.h>
34 #include <dbus/dbus-internals.h>
35 #include <dbus/dbus-marshal-recursive.h>
36 #include <string.h>
37
38 static dbus_bool_t bus_driver_send_welcome_message (DBusConnection *connection,
39                                                     DBusMessage    *hello_message,
40                                                     BusTransaction *transaction,
41                                                     DBusError      *error);
42
43 dbus_bool_t
44 bus_driver_send_service_owner_changed (const char     *service_name,
45                                        const char     *old_owner,
46                                        const char     *new_owner,
47                                        BusTransaction *transaction,
48                                        DBusError      *error)
49 {
50   DBusMessage *message;
51   dbus_bool_t retval;
52   const char *null_service;
53
54   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
55
56   null_service = "";
57   _dbus_verbose ("sending name owner changed: %s [%s -> %s]\n",
58                  service_name, 
59                  old_owner ? old_owner : null_service, 
60                  new_owner ? new_owner : null_service);
61
62   message = dbus_message_new_signal (DBUS_PATH_DBUS,
63                                      DBUS_INTERFACE_DBUS,
64                                      "NameOwnerChanged");
65   
66   if (message == NULL)
67     {
68       BUS_SET_OOM (error);
69       return FALSE;
70     }
71   
72   if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS))
73     goto oom;
74
75   if (!dbus_message_append_args (message,
76                                  DBUS_TYPE_STRING, &service_name,
77                                  DBUS_TYPE_STRING, old_owner ? &old_owner : &null_service,
78                                  DBUS_TYPE_STRING, new_owner ? &new_owner : &null_service,
79                                  DBUS_TYPE_INVALID))
80     goto oom;
81
82   _dbus_assert (dbus_message_has_signature (message, "sss"));
83   
84   retval = bus_dispatch_matches (transaction, NULL, NULL, message, error);
85   dbus_message_unref (message);
86
87   return retval;
88
89  oom:
90   dbus_message_unref (message);
91   BUS_SET_OOM (error);
92   return FALSE;
93 }
94
95 dbus_bool_t
96 bus_driver_send_service_lost (DBusConnection *connection,
97                               const char     *service_name,
98                               BusTransaction *transaction,
99                               DBusError      *error)
100 {
101   DBusMessage *message;
102
103   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
104   
105   message = dbus_message_new_signal (DBUS_PATH_DBUS,
106                                      DBUS_INTERFACE_DBUS,
107                                      "NameLost");
108   
109   if (message == NULL)
110     {
111       BUS_SET_OOM (error);
112       return FALSE;
113     }
114   
115   if (!dbus_message_set_destination (message, bus_connection_get_name (connection)) ||
116       !dbus_message_append_args (message,
117                                  DBUS_TYPE_STRING, &service_name,
118                                  DBUS_TYPE_INVALID))
119     {
120       dbus_message_unref (message);
121       BUS_SET_OOM (error);
122       return FALSE;
123     }
124
125   if (!bus_transaction_send_from_driver (transaction, connection, message))
126     {
127       dbus_message_unref (message);
128       BUS_SET_OOM (error);
129       return FALSE;
130     }
131   else
132     {
133       dbus_message_unref (message);
134       return TRUE;
135     }
136 }
137
138 dbus_bool_t
139 bus_driver_send_service_acquired (DBusConnection *connection,
140                                   const char     *service_name,
141                                   BusTransaction *transaction,
142                                   DBusError      *error)
143 {
144   DBusMessage *message;
145
146   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
147   
148   message = dbus_message_new_signal (DBUS_PATH_DBUS,
149                                      DBUS_INTERFACE_DBUS,
150                                      "NameAcquired");
151
152   if (message == NULL)
153     {
154       BUS_SET_OOM (error);
155       return FALSE;
156     }
157   
158   if (!dbus_message_set_destination (message, bus_connection_get_name (connection)) ||
159       !dbus_message_append_args (message,
160                                  DBUS_TYPE_STRING, &service_name,
161                                  DBUS_TYPE_INVALID))
162     {
163       dbus_message_unref (message);
164       BUS_SET_OOM (error);
165       return FALSE;
166     }
167
168   if (!bus_transaction_send_from_driver (transaction, connection, message))
169     {
170       dbus_message_unref (message);
171       BUS_SET_OOM (error);
172       return FALSE;
173     }
174   else
175     {
176       dbus_message_unref (message);
177       return TRUE;
178     }
179 }
180
181 static dbus_bool_t
182 create_unique_client_name (BusRegistry *registry,
183                            DBusString  *str)
184 {
185   /* We never want to use the same unique client name twice, because
186    * we want to guarantee that if you send a message to a given unique
187    * name, you always get the same application. So we use two numbers
188    * for INT_MAX * INT_MAX combinations, should be pretty safe against
189    * wraparound.
190    */
191   /* FIXME these should be in BusRegistry rather than static vars */
192   static int next_major_number = 0;
193   static int next_minor_number = 0;
194   int len;
195   
196   len = _dbus_string_get_length (str);
197   
198   while (TRUE)
199     {
200       /* start out with 1-0, go to 1-1, 1-2, 1-3,
201        * up to 1-MAXINT, then 2-0, 2-1, etc.
202        */
203       if (next_minor_number <= 0)
204         {
205           next_major_number += 1;
206           next_minor_number = 0;
207           if (next_major_number <= 0)
208             _dbus_assert_not_reached ("INT_MAX * INT_MAX clients were added");
209         }
210
211       _dbus_assert (next_major_number > 0);
212       _dbus_assert (next_minor_number >= 0);
213
214       /* appname:MAJOR-MINOR */
215       
216       if (!_dbus_string_append (str, ":"))
217         return FALSE;
218       
219       if (!_dbus_string_append_int (str, next_major_number))
220         return FALSE;
221
222       if (!_dbus_string_append (str, "."))
223         return FALSE;
224       
225       if (!_dbus_string_append_int (str, next_minor_number))
226         return FALSE;
227
228       next_minor_number += 1;
229       
230       /* Check if a client with the name exists */
231       if (bus_registry_lookup (registry, str) == NULL)
232         break;
233
234       /* drop the number again, try the next one. */
235       _dbus_string_set_length (str, len);
236     }
237
238   return TRUE;
239 }
240
241 static dbus_bool_t
242 bus_driver_handle_hello (DBusConnection *connection,
243                          BusTransaction *transaction,
244                          DBusMessage    *message,
245                          DBusError      *error)
246 {
247   DBusString unique_name;
248   BusService *service;
249   dbus_bool_t retval;
250   BusRegistry *registry;
251   BusConnections *connections;
252
253   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
254
255   if (bus_connection_is_active (connection))
256     {
257       /* We already handled an Hello message for this connection. */
258       dbus_set_error (error, DBUS_ERROR_FAILED,
259                       "Already handled an Hello message");
260       return FALSE;
261     }
262
263   /* Note that when these limits are exceeded we don't disconnect the
264    * connection; we just sort of leave it hanging there until it times
265    * out or disconnects itself or is dropped due to the max number of
266    * incomplete connections. It's even OK if the connection wants to
267    * retry the hello message, we support that.
268    */
269   connections = bus_connection_get_connections (connection);
270   if (!bus_connections_check_limits (connections, connection,
271                                      error))
272     {
273       _DBUS_ASSERT_ERROR_IS_SET (error);
274       return FALSE;
275     }
276   
277   if (!_dbus_string_init (&unique_name))
278     {
279       BUS_SET_OOM (error);
280       return FALSE;
281     }
282
283   retval = FALSE;
284
285   registry = bus_connection_get_registry (connection);
286   
287   if (!create_unique_client_name (registry, &unique_name))
288     {
289       BUS_SET_OOM (error);
290       goto out_0;
291     }
292
293   if (!bus_connection_complete (connection, &unique_name, error))
294     {
295       _DBUS_ASSERT_ERROR_IS_SET (error);
296       goto out_0;
297     }
298   
299   if (!dbus_message_set_sender (message,
300                                 bus_connection_get_name (connection)))
301     {
302       BUS_SET_OOM (error);
303       goto out_0;
304     }
305   
306   if (!bus_driver_send_welcome_message (connection, message, transaction, error))
307     goto out_0;
308
309   /* Create the service */
310   service = bus_registry_ensure (registry,
311                                  &unique_name, connection, transaction, error);
312   if (service == NULL)
313     goto out_0;
314   
315   bus_service_set_prohibit_replacement (service, TRUE);
316
317   _dbus_assert (bus_connection_is_active (connection));
318   retval = TRUE;
319   
320  out_0:
321   _dbus_string_free (&unique_name);
322   return retval;
323 }
324
325 static dbus_bool_t
326 bus_driver_send_welcome_message (DBusConnection *connection,
327                                  DBusMessage    *hello_message,
328                                  BusTransaction *transaction,
329                                  DBusError      *error)
330 {
331   DBusMessage *welcome;
332   const char *name;
333
334   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
335   
336   name = bus_connection_get_name (connection);
337   _dbus_assert (name != NULL);
338   
339   welcome = dbus_message_new_method_return (hello_message);
340   if (welcome == NULL)
341     {
342       BUS_SET_OOM (error);
343       return FALSE;
344     }
345   
346   if (!dbus_message_append_args (welcome,
347                                  DBUS_TYPE_STRING, &name,
348                                  DBUS_TYPE_INVALID))
349     {
350       dbus_message_unref (welcome);
351       BUS_SET_OOM (error);
352       return FALSE;
353     }
354
355   _dbus_assert (dbus_message_has_signature (welcome, DBUS_TYPE_STRING_AS_STRING));
356   
357   if (!bus_transaction_send_from_driver (transaction, connection, welcome))
358     {
359       dbus_message_unref (welcome);
360       BUS_SET_OOM (error);
361       return FALSE;
362     }
363   else
364     {
365       dbus_message_unref (welcome);
366       return TRUE;
367     }
368 }
369
370 static dbus_bool_t
371 bus_driver_handle_list_services (DBusConnection *connection,
372                                  BusTransaction *transaction,
373                                  DBusMessage    *message,
374                                  DBusError      *error)
375 {
376   DBusMessage *reply;
377   int len;
378   char **services;
379   BusRegistry *registry;
380   int i;
381   DBusMessageIter iter;
382   DBusMessageIter sub;
383
384   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
385   
386   registry = bus_connection_get_registry (connection);
387   
388   reply = dbus_message_new_method_return (message);
389   if (reply == NULL)
390     {
391       BUS_SET_OOM (error);
392       return FALSE;
393     }
394
395   if (!bus_registry_list_services (registry, &services, &len))
396     {
397       dbus_message_unref (reply);
398       BUS_SET_OOM (error);
399       return FALSE;
400     }
401
402   dbus_message_iter_init_append (reply, &iter);
403   
404   if (!dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY,
405                                          DBUS_TYPE_STRING_AS_STRING,
406                                          &sub))
407     {
408       dbus_free_string_array (services);
409       dbus_message_unref (reply);
410       BUS_SET_OOM (error);
411       return FALSE;
412     }
413
414   {
415     /* Include the bus driver in the list */
416     const char *v_STRING = DBUS_SERVICE_DBUS;
417     if (!dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING,
418                                          &v_STRING))
419       {
420         dbus_free_string_array (services);
421         dbus_message_unref (reply);
422         BUS_SET_OOM (error);
423         return FALSE;
424       }
425   }
426   
427   i = 0;
428   while (i < len)
429     {
430       if (!dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING,
431                                            &services[i]))
432         {
433           dbus_free_string_array (services);
434           dbus_message_unref (reply);
435           BUS_SET_OOM (error);
436           return FALSE;
437         }
438       ++i;
439     }
440
441   if (!dbus_message_iter_close_container (&iter, &sub))
442     {
443       dbus_free_string_array (services);
444       dbus_message_unref (reply);
445       BUS_SET_OOM (error);
446       return FALSE;
447     }
448   
449   dbus_free_string_array (services);
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_acquire_service (DBusConnection *connection,
466                                    BusTransaction *transaction,
467                                    DBusMessage    *message,
468                                    DBusError      *error)
469 {
470   DBusMessage *reply;
471   DBusString service_name;
472   const char *name;
473   dbus_uint32_t service_reply;
474   dbus_uint32_t flags;
475   dbus_bool_t retval;
476   BusRegistry *registry;
477
478   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
479   
480   registry = bus_connection_get_registry (connection);
481   
482   if (!dbus_message_get_args (message, error,
483                               DBUS_TYPE_STRING, &name,
484                               DBUS_TYPE_UINT32, &flags,
485                               DBUS_TYPE_INVALID))
486     return FALSE;
487   
488   _dbus_verbose ("Trying to own name %s with flags 0x%x\n", name, flags);
489   
490   retval = FALSE;
491   reply = NULL;
492
493   _dbus_string_init_const (&service_name, name);
494
495   if (!bus_registry_acquire_service (registry, connection,
496                                      &service_name, flags,
497                                      &service_reply, transaction,
498                                      error))
499     goto out;
500   
501   reply = dbus_message_new_method_return (message);
502   if (reply == NULL)
503     {
504       BUS_SET_OOM (error);
505       goto out;
506     }
507
508   if (!dbus_message_append_args (reply, DBUS_TYPE_UINT32, &service_reply, DBUS_TYPE_INVALID))
509     {
510       BUS_SET_OOM (error);
511       goto out;
512     }
513
514   if (!bus_transaction_send_from_driver (transaction, connection, reply))
515     {
516       BUS_SET_OOM (error);
517       goto out;
518     }
519
520   retval = TRUE;
521   
522  out:
523   if (reply)
524     dbus_message_unref (reply);
525   return retval;
526
527
528 static dbus_bool_t
529 bus_driver_handle_release_service (DBusConnection *connection,
530                                    BusTransaction *transaction,
531                                    DBusMessage    *message,
532                                    DBusError      *error)
533 {
534   DBusMessage *reply;
535   DBusString service_name;
536   const char *name;
537   dbus_uint32_t service_reply;
538   dbus_bool_t retval;
539   BusRegistry *registry;
540
541   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
542
543   registry = bus_connection_get_registry (connection);
544
545   if (!dbus_message_get_args (message, error,
546                               DBUS_TYPE_STRING, &name,
547                               DBUS_TYPE_INVALID))
548     return FALSE;
549
550   _dbus_verbose ("Trying to release name %s\n", name);
551
552   retval = FALSE;
553   reply = NULL;
554
555   _dbus_string_init_const (&service_name, name);
556
557   if (!bus_registry_release_service (registry, connection,
558                                      &service_name, &service_reply,
559                                      transaction, error))
560     goto out;
561
562   reply = dbus_message_new_method_return (message);
563   if (reply == NULL)
564     {
565       BUS_SET_OOM (error);
566       goto out;
567     }
568
569   if (!dbus_message_append_args (reply, DBUS_TYPE_UINT32, &service_reply, DBUS_TYPE_INVALID))
570     {
571       BUS_SET_OOM (error);
572       goto out;
573     }
574
575   if (!bus_transaction_send_from_driver (transaction, connection, reply))
576     {
577       BUS_SET_OOM (error);
578       goto out;
579     }
580
581   retval = TRUE;
582
583  out:
584   if (reply)
585     dbus_message_unref (reply);
586   return retval;
587 }
588
589 static dbus_bool_t
590 bus_driver_handle_service_exists (DBusConnection *connection,
591                                   BusTransaction *transaction,
592                                   DBusMessage    *message,
593                                   DBusError      *error)
594 {
595   DBusMessage *reply;
596   DBusString service_name;
597   BusService *service;
598   dbus_bool_t service_exists;
599   const char *name;
600   dbus_bool_t retval;
601   BusRegistry *registry;
602
603   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
604   
605   registry = bus_connection_get_registry (connection);
606   
607   if (!dbus_message_get_args (message, error,
608                               DBUS_TYPE_STRING, &name,
609                               DBUS_TYPE_INVALID))
610     return FALSE;
611
612   retval = FALSE;
613
614   if (strcmp (name, DBUS_SERVICE_DBUS) == 0)
615     {
616       service_exists = TRUE;
617     }
618   else
619     {
620       _dbus_string_init_const (&service_name, name);
621       service = bus_registry_lookup (registry, &service_name);
622       service_exists = service != NULL;
623     }
624   
625   reply = dbus_message_new_method_return (message);
626   if (reply == NULL)
627     {
628       BUS_SET_OOM (error);
629       goto out;
630     }
631
632   if (!dbus_message_append_args (reply,
633                                  DBUS_TYPE_BOOLEAN, &service_exists,
634                                  0))
635     {
636       BUS_SET_OOM (error);
637       goto out;
638     }
639
640   if (!bus_transaction_send_from_driver (transaction, connection, reply))
641     {
642       BUS_SET_OOM (error);
643       goto out;
644     }
645
646   retval = TRUE;
647   
648  out:
649   if (reply)
650     dbus_message_unref (reply);
651
652   return retval;
653 }
654
655 static dbus_bool_t
656 bus_driver_handle_activate_service (DBusConnection *connection,
657                                     BusTransaction *transaction,
658                                     DBusMessage    *message,
659                                     DBusError      *error)
660 {
661   dbus_uint32_t flags;
662   const char *name;
663   dbus_bool_t retval;
664   BusActivation *activation;
665
666   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
667   
668   activation = bus_connection_get_activation (connection);
669   
670   if (!dbus_message_get_args (message, error,
671                               DBUS_TYPE_STRING, &name,
672                               DBUS_TYPE_UINT32, &flags,
673                               DBUS_TYPE_INVALID))
674     {
675       _DBUS_ASSERT_ERROR_IS_SET (error);
676       _dbus_verbose ("No memory to get arguments to StartServiceByName\n");
677       return FALSE;
678     }
679
680   retval = FALSE;
681
682   if (!bus_activation_activate_service (activation, connection, transaction, FALSE,
683                                         message, name, error))
684     {
685       _DBUS_ASSERT_ERROR_IS_SET (error);
686       _dbus_verbose ("bus_activation_activate_service() failed\n");
687       goto out;
688     }
689
690   retval = TRUE;
691   
692  out:
693   return retval;
694 }
695
696 static dbus_bool_t
697 send_ack_reply (DBusConnection *connection,
698                 BusTransaction *transaction,
699                 DBusMessage    *message,
700                 DBusError      *error)
701 {
702   DBusMessage *reply;
703
704   reply = dbus_message_new_method_return (message);
705   if (reply == NULL)
706     {
707       BUS_SET_OOM (error);
708       return FALSE;
709     }
710
711   if (!bus_transaction_send_from_driver (transaction, connection, reply))
712     {
713       BUS_SET_OOM (error);
714       dbus_message_unref (reply);
715       return FALSE;
716     }
717
718   dbus_message_unref (reply);
719   
720   return TRUE;
721 }
722
723 static dbus_bool_t
724 bus_driver_handle_add_match (DBusConnection *connection,
725                              BusTransaction *transaction,
726                              DBusMessage    *message,
727                              DBusError      *error)
728 {
729   BusMatchRule *rule;
730   const char *text;
731   DBusString str;
732   BusMatchmaker *matchmaker;
733   
734   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
735
736   text = NULL;
737   rule = NULL;
738
739   if (bus_connection_get_n_match_rules (connection) >=
740       bus_context_get_max_match_rules_per_connection (bus_transaction_get_context (transaction)))
741     {
742       dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
743                       "Connection \"%s\" is not allowed to add more match rules "
744                       "(increase limits in configuration file if required)",
745                       bus_connection_is_active (connection) ?
746                       bus_connection_get_name (connection) :
747                       "(inactive)");
748       goto failed;
749     }
750   
751   if (!dbus_message_get_args (message, error,
752                               DBUS_TYPE_STRING, &text,
753                               DBUS_TYPE_INVALID))
754     {
755       _dbus_verbose ("No memory to get arguments to AddMatch\n");
756       goto failed;
757     }
758
759   _dbus_string_init_const (&str, text);
760
761   rule = bus_match_rule_parse (connection, &str, error);
762   if (rule == NULL)
763     goto failed;
764
765   matchmaker = bus_connection_get_matchmaker (connection);
766
767   if (!bus_matchmaker_add_rule (matchmaker, rule))
768     {
769       BUS_SET_OOM (error);
770       goto failed;
771     }
772
773   if (!send_ack_reply (connection, transaction,
774                        message, error))
775     {
776       bus_matchmaker_remove_rule (matchmaker, rule);
777       goto failed;
778     }
779   
780   bus_match_rule_unref (rule);
781   
782   return TRUE;
783
784  failed:
785   _DBUS_ASSERT_ERROR_IS_SET (error);
786   if (rule)
787     bus_match_rule_unref (rule);
788   return FALSE;
789 }
790
791 static dbus_bool_t
792 bus_driver_handle_remove_match (DBusConnection *connection,
793                                 BusTransaction *transaction,
794                                 DBusMessage    *message,
795                                 DBusError      *error)
796 {
797   BusMatchRule *rule;
798   const char *text;
799   DBusString str;
800   BusMatchmaker *matchmaker;
801   
802   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
803
804   text = NULL;
805   rule = NULL;
806   
807   if (!dbus_message_get_args (message, error,
808                               DBUS_TYPE_STRING, &text,
809                               DBUS_TYPE_INVALID))
810     {
811       _dbus_verbose ("No memory to get arguments to RemoveMatch\n");
812       goto failed;
813     }
814
815   _dbus_string_init_const (&str, text);
816
817   rule = bus_match_rule_parse (connection, &str, error);
818   if (rule == NULL)
819     goto failed;
820
821   /* Send the ack before we remove the rule, since the ack is undone
822    * on transaction cancel, but rule removal isn't.
823    */
824   if (!send_ack_reply (connection, transaction,
825                        message, error))
826     goto failed;
827   
828   matchmaker = bus_connection_get_matchmaker (connection);
829
830   if (!bus_matchmaker_remove_rule_by_value (matchmaker, rule, error))
831     goto failed;
832
833   bus_match_rule_unref (rule);
834   
835   return TRUE;
836
837  failed:
838   _DBUS_ASSERT_ERROR_IS_SET (error);
839   if (rule)
840     bus_match_rule_unref (rule);
841   return FALSE;
842 }
843
844 static dbus_bool_t
845 bus_driver_handle_get_service_owner (DBusConnection *connection,
846                                      BusTransaction *transaction,
847                                      DBusMessage    *message,
848                                      DBusError      *error)
849 {
850   const char *text;
851   const char *base_name;
852   DBusString str;
853   BusRegistry *registry;
854   BusService *service;
855   DBusMessage *reply;
856   
857   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
858
859   registry = bus_connection_get_registry (connection);
860
861   text = NULL;
862   reply = NULL;
863
864   if (! dbus_message_get_args (message, error,
865                                DBUS_TYPE_STRING, &text,
866                                DBUS_TYPE_INVALID))
867       goto failed;
868
869   _dbus_string_init_const (&str, text);
870   service = bus_registry_lookup (registry, &str);
871   if (service == NULL &&
872       _dbus_string_equal_c_str (&str, DBUS_SERVICE_DBUS))
873     {
874       /* ORG_FREEDESKTOP_DBUS owns itself */
875       base_name = DBUS_SERVICE_DBUS;
876     }
877   else if (service == NULL)
878     {
879       dbus_set_error (error, 
880                       DBUS_ERROR_NAME_HAS_NO_OWNER,
881                       "Could not get owner of name '%s': no such name", text);
882       goto failed;
883     }
884   else
885     {
886       base_name = bus_connection_get_name (bus_service_get_primary_owner (service));
887       if (base_name == NULL)
888         {
889           /* FIXME - how is this error possible? */
890           dbus_set_error (error,
891                           DBUS_ERROR_FAILED,
892                           "Could not determine unique name for '%s'", text);
893           goto failed;
894         }
895       _dbus_assert (*base_name == ':');      
896     }
897
898   _dbus_assert (base_name != NULL);
899
900   reply = dbus_message_new_method_return (message);
901   if (reply == NULL)
902     goto oom;
903
904   if (! dbus_message_append_args (reply, 
905                                   DBUS_TYPE_STRING, &base_name,
906                                   DBUS_TYPE_INVALID))
907     goto oom;
908   
909   if (! bus_transaction_send_from_driver (transaction, connection, reply))
910     goto oom;
911
912   dbus_message_unref (reply);
913
914   return TRUE;
915
916  oom:
917   BUS_SET_OOM (error);
918
919  failed:
920   _DBUS_ASSERT_ERROR_IS_SET (error);
921   if (reply)
922     dbus_message_unref (reply);
923   return FALSE;
924 }
925
926 static dbus_bool_t
927 bus_driver_handle_get_connection_unix_user (DBusConnection *connection,
928                                             BusTransaction *transaction,
929                                             DBusMessage    *message,
930                                             DBusError      *error)
931 {
932   const char *service;
933   DBusString str;
934   BusRegistry *registry;
935   BusService *serv;
936   DBusConnection *conn;
937   DBusMessage *reply;
938   unsigned long uid;
939   dbus_uint32_t uid32;
940
941   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
942
943   registry = bus_connection_get_registry (connection);
944
945   service = NULL;
946   reply = NULL;
947
948   if (! dbus_message_get_args (message, error,
949                                DBUS_TYPE_STRING, &service,
950                                DBUS_TYPE_INVALID))
951       goto failed;
952
953   _dbus_verbose ("asked for UID of connection %s\n", service);
954
955   _dbus_string_init_const (&str, service);
956   serv = bus_registry_lookup (registry, &str);
957   if (serv == NULL)
958     {
959       dbus_set_error (error, 
960                       DBUS_ERROR_NAME_HAS_NO_OWNER,
961                       "Could not get UID of name '%s': no such name", service);
962       goto failed;
963     }
964
965   conn = bus_service_get_primary_owner (serv);
966
967   reply = dbus_message_new_method_return (message);
968   if (reply == NULL)
969     goto oom;
970
971   if (!dbus_connection_get_unix_user (conn, &uid))
972     {
973       dbus_set_error (error,
974                       DBUS_ERROR_FAILED,
975                       "Could not determine UID for '%s'", service);
976       goto failed;
977     }
978
979   uid32 = uid;
980   if (! dbus_message_append_args (reply,
981                                   DBUS_TYPE_UINT32, &uid32,
982                                   DBUS_TYPE_INVALID))
983     goto oom;
984
985   if (! bus_transaction_send_from_driver (transaction, connection, reply))
986     goto oom;
987
988   dbus_message_unref (reply);
989
990   return TRUE;
991
992  oom:
993   BUS_SET_OOM (error);
994
995  failed:
996   _DBUS_ASSERT_ERROR_IS_SET (error);
997   if (reply)
998     dbus_message_unref (reply);
999   return FALSE;
1000 }
1001
1002 static dbus_bool_t
1003 bus_driver_handle_get_connection_unix_process_id (DBusConnection *connection,
1004                                                   BusTransaction *transaction,
1005                                                   DBusMessage    *message,
1006                                                   DBusError      *error)
1007 {
1008   const char *service;
1009   DBusString str;
1010   BusRegistry *registry;
1011   BusService *serv;
1012   DBusConnection *conn;
1013   DBusMessage *reply;
1014   unsigned long pid;
1015   dbus_uint32_t pid32;
1016
1017   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1018
1019   registry = bus_connection_get_registry (connection);
1020
1021   service = NULL;
1022   reply = NULL;
1023
1024   if (! dbus_message_get_args (message, error,
1025                                DBUS_TYPE_STRING, &service,
1026                                DBUS_TYPE_INVALID))
1027       goto failed;
1028
1029   _dbus_verbose ("asked for PID of connection %s\n", service);
1030
1031   _dbus_string_init_const (&str, service);
1032   serv = bus_registry_lookup (registry, &str);
1033   if (serv == NULL)
1034     {
1035       dbus_set_error (error, 
1036                       DBUS_ERROR_NAME_HAS_NO_OWNER,
1037                       "Could not get PID of name '%s': no such name", service);
1038       goto failed;
1039     }
1040
1041   conn = bus_service_get_primary_owner (serv);
1042
1043   reply = dbus_message_new_method_return (message);
1044   if (reply == NULL)
1045     goto oom;
1046
1047   if (!dbus_connection_get_unix_process_id (conn, &pid))
1048     {
1049       dbus_set_error (error,
1050                       DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN,
1051                       "Could not determine PID for '%s'", service);
1052       goto failed;
1053     }
1054
1055   pid32 = pid;
1056   if (! dbus_message_append_args (reply,
1057                                   DBUS_TYPE_UINT32, &pid32,
1058                                   DBUS_TYPE_INVALID))
1059     goto oom;
1060
1061   if (! bus_transaction_send_from_driver (transaction, connection, reply))
1062     goto oom;
1063
1064   dbus_message_unref (reply);
1065
1066   return TRUE;
1067
1068  oom:
1069   BUS_SET_OOM (error);
1070
1071  failed:
1072   _DBUS_ASSERT_ERROR_IS_SET (error);
1073   if (reply)
1074     dbus_message_unref (reply);
1075   return FALSE;
1076 }
1077
1078 static dbus_bool_t
1079 bus_driver_handle_get_connection_selinux_security_context (DBusConnection *connection,
1080                                                            BusTransaction *transaction,
1081                                                            DBusMessage    *message,
1082                                                            DBusError      *error)
1083 {
1084   const char *service;
1085   DBusString str;
1086   BusRegistry *registry;
1087   BusService *serv;
1088   DBusConnection *conn;
1089   DBusMessage *reply;
1090   BusSELinuxID *context;
1091
1092   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1093
1094   registry = bus_connection_get_registry (connection);
1095
1096   service = NULL;
1097   reply = NULL;
1098
1099   if (! dbus_message_get_args (message, error,
1100                                DBUS_TYPE_STRING, &service,
1101                                DBUS_TYPE_INVALID))
1102       goto failed;
1103
1104   _dbus_verbose ("asked for security context of connection %s\n", service);
1105
1106   _dbus_string_init_const (&str, service);
1107   serv = bus_registry_lookup (registry, &str);
1108   if (serv == NULL)
1109     {
1110       dbus_set_error (error, 
1111                       DBUS_ERROR_NAME_HAS_NO_OWNER,
1112                       "Could not get security context of name '%s': no such name", service);
1113       goto failed;
1114     }
1115
1116   conn = bus_service_get_primary_owner (serv);
1117
1118   reply = dbus_message_new_method_return (message);
1119   if (reply == NULL)
1120     goto oom;
1121
1122   context = bus_connection_get_selinux_id (conn);
1123   if (!context)
1124     {
1125       dbus_set_error (error,
1126                       DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN,
1127                       "Could not determine security context for '%s'", service);
1128       goto failed;
1129     }
1130
1131   if (! bus_selinux_append_context (reply, context, error))
1132     goto failed;
1133
1134   if (! bus_transaction_send_from_driver (transaction, connection, reply))
1135     goto oom;
1136
1137   dbus_message_unref (reply);
1138
1139   return TRUE;
1140
1141  oom:
1142   BUS_SET_OOM (error);
1143
1144  failed:
1145   _DBUS_ASSERT_ERROR_IS_SET (error);
1146   if (reply)
1147     dbus_message_unref (reply);
1148   return FALSE;
1149 }
1150
1151 static dbus_bool_t
1152 bus_driver_handle_reload_config (DBusConnection *connection,
1153                                  BusTransaction *transaction,
1154                                  DBusMessage    *message,
1155                                  DBusError      *error)
1156 {
1157   BusContext *context;
1158   DBusMessage *reply;
1159
1160   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1161
1162   reply = NULL;
1163   
1164   context = bus_connection_get_context (connection);
1165   if (!bus_context_reload_config (context, error))
1166     goto failed;
1167
1168   reply = dbus_message_new_method_return (message);
1169   if (reply == NULL)
1170     goto oom;
1171
1172   if (! bus_transaction_send_from_driver (transaction, connection, reply))
1173     goto oom;
1174
1175   dbus_message_unref (reply);
1176   return TRUE;
1177
1178  oom:
1179   BUS_SET_OOM (error);
1180
1181  failed:
1182   _DBUS_ASSERT_ERROR_IS_SET (error);
1183   if (reply)
1184     dbus_message_unref (reply);
1185   return FALSE;
1186 }
1187
1188 /* For speed it might be useful to sort this in order of
1189  * frequency of use (but doesn't matter with only a few items
1190  * anyhow)
1191  */
1192 struct
1193 {
1194   const char *name;
1195   const char *in_args;
1196   const char *out_args;
1197   dbus_bool_t (* handler) (DBusConnection *connection,
1198                            BusTransaction *transaction,
1199                            DBusMessage    *message,
1200                            DBusError      *error);
1201 } message_handlers[] = {
1202   { "RequestName",
1203     DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_UINT32_AS_STRING,
1204     DBUS_TYPE_UINT32_AS_STRING,
1205     bus_driver_handle_acquire_service },
1206   { "ReleaseName",
1207     DBUS_TYPE_STRING_AS_STRING,
1208     DBUS_TYPE_UINT32_AS_STRING,
1209     bus_driver_handle_release_service },
1210   { "StartServiceByName",
1211     DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_UINT32_AS_STRING,
1212     DBUS_TYPE_UINT32_AS_STRING,
1213     bus_driver_handle_activate_service },
1214   { "Hello",
1215     "",
1216     DBUS_TYPE_STRING_AS_STRING,
1217     bus_driver_handle_hello },
1218   { "NameHasOwner",
1219     DBUS_TYPE_STRING_AS_STRING,
1220     DBUS_TYPE_BOOLEAN_AS_STRING,
1221     bus_driver_handle_service_exists },
1222   { "ListNames",
1223     "",
1224     DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
1225     bus_driver_handle_list_services },
1226   { "AddMatch",
1227     DBUS_TYPE_STRING_AS_STRING,
1228     "",
1229     bus_driver_handle_add_match },
1230   { "RemoveMatch",
1231     DBUS_TYPE_STRING_AS_STRING,
1232     "",
1233     bus_driver_handle_remove_match },
1234   { "GetNameOwner",
1235     DBUS_TYPE_STRING_AS_STRING,
1236     DBUS_TYPE_STRING_AS_STRING,
1237     bus_driver_handle_get_service_owner },
1238   { "GetConnectionUnixUser",
1239     DBUS_TYPE_STRING_AS_STRING,
1240     DBUS_TYPE_UINT32_AS_STRING,
1241     bus_driver_handle_get_connection_unix_user },
1242   { "GetConnectionUnixProcessID",
1243     DBUS_TYPE_STRING_AS_STRING,
1244     DBUS_TYPE_UINT32_AS_STRING,
1245     bus_driver_handle_get_connection_unix_process_id },
1246   { "GetConnectionSELinuxSecurityContext",
1247     DBUS_TYPE_STRING_AS_STRING,
1248     DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING,
1249     bus_driver_handle_get_connection_selinux_security_context },
1250   { "ReloadConfig",
1251     "",
1252     "",
1253     bus_driver_handle_reload_config }
1254 };
1255
1256 static dbus_bool_t
1257 write_args_for_direction (DBusString *xml,
1258                           const char *signature,
1259                           dbus_bool_t in)
1260 {
1261   DBusTypeReader typereader;
1262   DBusString sigstr;
1263   int current_type;
1264   
1265   _dbus_string_init_const (&sigstr, signature);
1266   _dbus_type_reader_init_types_only (&typereader, &sigstr, 0);
1267       
1268   while ((current_type = _dbus_type_reader_get_current_type (&typereader)) != DBUS_TYPE_INVALID)
1269     {
1270       const DBusString *subsig;
1271       int start, len;
1272
1273       _dbus_type_reader_get_signature (&typereader, &subsig, &start, &len);
1274       if (!_dbus_string_append_printf (xml, "      <arg direction=\"%s\" type=\"",
1275                                        in ? "in" : "out"))
1276         goto oom;
1277       if (!_dbus_string_append_len (xml,
1278                                     _dbus_string_get_const_data (subsig) + start,
1279                                     len))
1280         goto oom;
1281       if (!_dbus_string_append (xml, "\"/>\n"))
1282         goto oom;
1283
1284       _dbus_type_reader_next (&typereader);
1285     }
1286   return TRUE;
1287  oom:
1288   return FALSE;
1289 }
1290
1291 static dbus_bool_t
1292 bus_driver_handle_introspect (DBusConnection *connection,
1293                               BusTransaction *transaction,
1294                               DBusMessage    *message,
1295                               DBusError      *error)
1296 {
1297   DBusString xml;
1298   DBusMessage *reply;
1299   const char *v_STRING;
1300   int i;
1301
1302   _dbus_verbose ("Introspect() on bus driver\n");
1303   
1304   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1305
1306   reply = NULL;
1307
1308   if (! dbus_message_get_args (message, error,
1309                                DBUS_TYPE_INVALID))
1310     {
1311       _DBUS_ASSERT_ERROR_IS_SET (error);
1312       return FALSE;
1313     }
1314
1315   if (!_dbus_string_init (&xml))
1316     {
1317       BUS_SET_OOM (error);
1318       return FALSE;
1319     }
1320
1321   if (!_dbus_string_append (&xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE))
1322     goto oom;
1323   if (!_dbus_string_append (&xml, "<node>\n"))
1324     goto oom;
1325   if (!_dbus_string_append_printf (&xml, "  <interface name=\"%s\">\n", DBUS_INTERFACE_INTROSPECTABLE))
1326     goto oom;
1327   if (!_dbus_string_append (&xml, "    <method name=\"Introspect\">\n"))
1328     goto oom;
1329   if (!_dbus_string_append_printf (&xml, "      <arg name=\"data\" direction=\"out\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING))
1330     goto oom;
1331   if (!_dbus_string_append (&xml, "    </method>\n"))
1332     goto oom;
1333   if (!_dbus_string_append (&xml, "  </interface>\n"))
1334     goto oom;
1335
1336   if (!_dbus_string_append_printf (&xml, "  <interface name=\"%s\">\n",
1337                                    DBUS_INTERFACE_DBUS))
1338     goto oom;
1339
1340   i = 0;
1341   while (i < _DBUS_N_ELEMENTS (message_handlers))
1342     {
1343           
1344       if (!_dbus_string_append_printf (&xml, "    <method name=\"%s\">\n",
1345                                        message_handlers[i].name))
1346         goto oom;
1347
1348       if (!write_args_for_direction (&xml, message_handlers[i].in_args, TRUE))
1349         goto oom;
1350
1351       if (!write_args_for_direction (&xml, message_handlers[i].out_args, FALSE))
1352         goto oom;
1353
1354       if (!_dbus_string_append (&xml, "    </method>\n"))
1355         goto oom;
1356       
1357       ++i;
1358     }
1359
1360   if (!_dbus_string_append_printf (&xml, "    <signal name=\"NameOwnerChanged\">\n"))
1361     goto oom;
1362   
1363   if (!_dbus_string_append_printf (&xml, "      <arg type=\"s\"/>\n"))
1364     goto oom;
1365   
1366   if (!_dbus_string_append_printf (&xml, "      <arg type=\"s\"/>\n"))
1367     goto oom;
1368   
1369   if (!_dbus_string_append_printf (&xml, "      <arg type=\"s\"/>\n"))
1370     goto oom;
1371   
1372   if (!_dbus_string_append_printf (&xml, "    </signal>\n"))
1373     goto oom;
1374
1375
1376
1377   if (!_dbus_string_append_printf (&xml, "    <signal name=\"NameLost\">\n"))
1378     goto oom;
1379   
1380   if (!_dbus_string_append_printf (&xml, "      <arg type=\"s\"/>\n"))
1381     goto oom;
1382   
1383   if (!_dbus_string_append_printf (&xml, "    </signal>\n"))
1384     goto oom;
1385
1386
1387
1388   if (!_dbus_string_append_printf (&xml, "    <signal name=\"NameAcquired\">\n"))
1389     goto oom;
1390   
1391   if (!_dbus_string_append_printf (&xml, "      <arg type=\"s\"/>\n"))
1392     goto oom;
1393   
1394   if (!_dbus_string_append_printf (&xml, "    </signal>\n"))
1395     goto oom;
1396
1397
1398   
1399   if (!_dbus_string_append (&xml, "  </interface>\n"))
1400     goto oom;
1401   
1402   if (!_dbus_string_append (&xml, "</node>\n"))
1403     goto oom;
1404
1405   reply = dbus_message_new_method_return (message);
1406   if (reply == NULL)
1407     goto oom;
1408
1409   v_STRING = _dbus_string_get_const_data (&xml);
1410   if (! dbus_message_append_args (reply,
1411                                   DBUS_TYPE_STRING, &v_STRING,
1412                                   DBUS_TYPE_INVALID))
1413     goto oom;
1414
1415   if (! bus_transaction_send_from_driver (transaction, connection, reply))
1416     goto oom;
1417
1418   dbus_message_unref (reply);
1419   _dbus_string_free (&xml);
1420
1421   return TRUE;
1422
1423  oom:
1424   BUS_SET_OOM (error);
1425
1426   if (reply)
1427     dbus_message_unref (reply);
1428
1429   _dbus_string_free (&xml);
1430   
1431   return FALSE;
1432 }
1433
1434 dbus_bool_t
1435 bus_driver_handle_message (DBusConnection *connection,
1436                            BusTransaction *transaction,
1437                            DBusMessage    *message,
1438                            DBusError      *error)
1439 {
1440   const char *name, *sender, *interface;
1441   int i;
1442
1443   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1444
1445   if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL)
1446     {
1447       _dbus_verbose ("Driver got a non-method-call message, ignoring\n");
1448       return TRUE; /* we just ignore this */
1449     }
1450
1451   if (dbus_message_is_method_call (message,
1452                                    DBUS_INTERFACE_INTROSPECTABLE,
1453                                    "Introspect"))
1454     return bus_driver_handle_introspect (connection, transaction, message, error);
1455   
1456   interface = dbus_message_get_interface (message);
1457   if (interface == NULL)
1458     interface = DBUS_INTERFACE_DBUS;
1459   
1460   _dbus_assert (dbus_message_get_member (message) != NULL);
1461   
1462   name = dbus_message_get_member (message);
1463   sender = dbus_message_get_sender (message);
1464   
1465   if (strcmp (interface,
1466               DBUS_INTERFACE_DBUS) != 0)
1467     {
1468       _dbus_verbose ("Driver got message to unknown interface \"%s\"\n",
1469                      interface);
1470       goto unknown;
1471     }
1472   
1473   _dbus_verbose ("Driver got a method call: %s\n",
1474                  dbus_message_get_member (message));
1475   
1476   /* security checks should have kept this from getting here */
1477   _dbus_assert (sender != NULL || strcmp (name, "Hello") == 0);
1478   
1479   i = 0;
1480   while (i < _DBUS_N_ELEMENTS (message_handlers))
1481     {
1482       if (strcmp (message_handlers[i].name, name) == 0)
1483         {
1484           _dbus_verbose ("Found driver handler for %s\n", name);
1485
1486           if (!dbus_message_has_signature (message, message_handlers[i].in_args))
1487             {
1488               _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1489               _dbus_verbose ("Call to %s has wrong args (%s, expected %s)\n",
1490                              name, dbus_message_get_signature (message),
1491                              message_handlers[i].in_args);
1492               
1493               dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
1494                               "Call to %s has wrong args (%s, expected %s)\n",
1495                               name, dbus_message_get_signature (message),
1496                               message_handlers[i].in_args);
1497               _DBUS_ASSERT_ERROR_IS_SET (error);
1498               return FALSE;
1499             }
1500           
1501           if ((* message_handlers[i].handler) (connection, transaction, message, error))
1502             {
1503               _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1504               _dbus_verbose ("Driver handler succeeded\n");
1505               return TRUE;
1506             }
1507           else
1508             {
1509               _DBUS_ASSERT_ERROR_IS_SET (error);
1510               _dbus_verbose ("Driver handler returned failure\n");
1511               return FALSE;
1512             }
1513         }
1514       
1515       ++i;
1516     }
1517
1518  unknown:
1519   _dbus_verbose ("No driver handler for message \"%s\"\n",
1520                  name);
1521
1522   dbus_set_error (error, DBUS_ERROR_UNKNOWN_METHOD,
1523                   "%s does not understand message %s",
1524                   DBUS_SERVICE_DBUS, name);
1525   
1526   return FALSE;
1527 }
1528
1529 void
1530 bus_driver_remove_connection (DBusConnection *connection)
1531 {
1532   /* FIXME Does nothing for now, should unregister the connection
1533    * with the bus driver.
1534    */
1535 }