2003-04-06 Havoc Pennington <hp@pobox.com>
[platform/upstream/dbus.git] / bus / bus.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* bus.c  message bus context object
3  *
4  * Copyright (C) 2003 Red Hat, Inc.
5  *
6  * Licensed under the Academic Free License version 1.2
7  * 
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  * 
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23
24 #include "bus.h"
25 #include "loop.h"
26 #include "activation.h"
27 #include "connection.h"
28 #include "services.h"
29 #include "utils.h"
30 #include "policy.h"
31 #include "config-parser.h"
32 #include <dbus/dbus-list.h>
33 #include <dbus/dbus-hash.h>
34 #include <dbus/dbus-internals.h>
35
36 struct BusContext
37 {
38   int refcount;
39   char *type;
40   char *address;
41   BusLoop *loop;
42   DBusList *servers;
43   BusConnections *connections;
44   BusActivation *activation;
45   BusRegistry *registry;
46   DBusList *default_rules;       /**< Default policy rules */
47   DBusList *mandatory_rules;     /**< Mandatory policy rules */
48   DBusHashTable *rules_by_uid;   /**< per-UID policy rules */
49   DBusHashTable *rules_by_gid;   /**< per-GID policy rules */
50   int activation_timeout;        /**< How long to wait for an activation to time out */
51   int auth_timeout;              /**< How long to wait for an authentication to time out */
52   int max_completed_connections;    /**< Max number of authorized connections */
53   int max_incomplete_connections;   /**< Max number of incomplete connections */
54   int max_connections_per_user;     /**< Max number of connections auth'd as same user */
55 };
56
57 static int server_data_slot = -1;
58 static int server_data_slot_refcount = 0;
59
60 typedef struct
61 {
62   BusContext *context;
63 } BusServerData;
64
65 #define BUS_SERVER_DATA(server) (dbus_server_get_data ((server), server_data_slot))
66
67 static dbus_bool_t
68 server_data_slot_ref (void)
69 {
70   if (server_data_slot < 0)
71     {
72       server_data_slot = dbus_server_allocate_data_slot ();
73       
74       if (server_data_slot < 0)
75         return FALSE;
76
77       _dbus_assert (server_data_slot_refcount == 0);
78     }  
79
80   server_data_slot_refcount += 1;
81
82   return TRUE;
83 }
84
85 static void
86 server_data_slot_unref (void)
87 {
88   _dbus_assert (server_data_slot_refcount > 0);
89
90   server_data_slot_refcount -= 1;
91   
92   if (server_data_slot_refcount == 0)
93     {
94       dbus_server_free_data_slot (server_data_slot);
95       server_data_slot = -1;
96     }
97 }
98
99 static BusContext*
100 server_get_context (DBusServer *server)
101 {
102   BusContext *context;
103   BusServerData *bd;
104   
105   if (!server_data_slot_ref ())
106     return NULL;
107
108   bd = BUS_SERVER_DATA (server);
109   if (bd == NULL)
110     {
111       server_data_slot_unref ();
112       return NULL;
113     }
114
115   context = bd->context;
116
117   server_data_slot_unref ();
118
119   return context;
120 }
121
122 static dbus_bool_t
123 server_watch_callback (DBusWatch     *watch,
124                        unsigned int   condition,
125                        void          *data)
126 {
127   DBusServer *server = data;
128
129   return dbus_server_handle_watch (server, watch, condition);
130 }
131
132 static dbus_bool_t
133 add_server_watch (DBusWatch  *watch,
134                   void       *data)
135 {
136   DBusServer *server = data;
137   BusContext *context;
138   
139   context = server_get_context (server);
140   
141   return bus_loop_add_watch (context->loop,
142                              watch, server_watch_callback, server,
143                              NULL);
144 }
145
146 static void
147 remove_server_watch (DBusWatch  *watch,
148                      void       *data)
149 {
150   DBusServer *server = data;
151   BusContext *context;
152   
153   context = server_get_context (server);
154   
155   bus_loop_remove_watch (context->loop,
156                          watch, server_watch_callback, server);
157 }
158
159
160 static void
161 server_timeout_callback (DBusTimeout   *timeout,
162                          void          *data)
163 {
164   /* can return FALSE on OOM but we just let it fire again later */
165   dbus_timeout_handle (timeout);
166 }
167
168 static dbus_bool_t
169 add_server_timeout (DBusTimeout *timeout,
170                     void        *data)
171 {
172   DBusServer *server = data;
173   BusContext *context;
174   
175   context = server_get_context (server);
176
177   return bus_loop_add_timeout (context->loop,
178                                timeout, server_timeout_callback, server, NULL);
179 }
180
181 static void
182 remove_server_timeout (DBusTimeout *timeout,
183                        void        *data)
184 {
185   DBusServer *server = data;
186   BusContext *context;
187   
188   context = server_get_context (server);
189   
190   bus_loop_remove_timeout (context->loop,
191                            timeout, server_timeout_callback, server);
192 }
193
194 static void
195 new_connection_callback (DBusServer     *server,
196                          DBusConnection *new_connection,
197                          void           *data)
198 {
199   BusContext *context = data;
200   
201   if (!bus_connections_setup_connection (context->connections, new_connection))
202     {
203       _dbus_verbose ("No memory to setup new connection\n");
204
205       /* if we don't do this, it will get unref'd without
206        * being disconnected... kind of strange really
207        * that we have to do this, people won't get it right
208        * in general.
209        */
210       dbus_connection_disconnect (new_connection);
211     }
212   
213   /* on OOM, we won't have ref'd the connection so it will die. */
214 }
215
216 static void
217 free_rule_func (void *data,
218                 void *user_data)
219 {
220   BusPolicyRule *rule = data;
221
222   bus_policy_rule_unref (rule);
223 }
224
225 static void
226 free_rule_list_func (void *data)
227 {
228   DBusList **list = data;
229
230   _dbus_list_foreach (list, free_rule_func, NULL);
231   
232   _dbus_list_clear (list);
233
234   dbus_free (list);
235 }
236
237 static void
238 free_server_data (void *data)
239 {
240   BusServerData *bd = data;  
241   
242   dbus_free (bd);
243 }
244
245 static dbus_bool_t
246 setup_server (BusContext *context,
247               DBusServer *server,
248               char      **auth_mechanisms,
249               DBusError  *error)
250 {
251   BusServerData *bd;
252
253   bd = dbus_new0 (BusServerData, 1);
254   if (!dbus_server_set_data (server,
255                              server_data_slot,
256                              bd, free_server_data))
257     {
258       dbus_free (bd);
259       BUS_SET_OOM (error);
260       return FALSE;
261     }
262
263   bd->context = context;
264   
265   if (!dbus_server_set_auth_mechanisms (server, (const char**) auth_mechanisms))
266     {
267       BUS_SET_OOM (error);
268       return FALSE;
269     }
270   
271   dbus_server_set_new_connection_function (server,
272                                            new_connection_callback,
273                                            context, NULL);
274   
275   if (!dbus_server_set_watch_functions (server,
276                                         add_server_watch,
277                                         remove_server_watch,
278                                         NULL,
279                                         server,
280                                         NULL))
281     {
282       BUS_SET_OOM (error);
283       return FALSE;
284     }
285
286   if (!dbus_server_set_timeout_functions (server,
287                                           add_server_timeout,
288                                           remove_server_timeout,
289                                           NULL,
290                                           server, NULL))
291     {
292       BUS_SET_OOM (error);
293       return FALSE;
294     }
295   
296   return TRUE;
297 }
298
299 BusContext*
300 bus_context_new (const DBusString *config_file,
301                  DBusError        *error)
302 {
303   BusContext *context;
304   DBusList *link;
305   DBusList **addresses;
306   BusConfigParser *parser;
307   DBusString full_address;
308   const char *user;
309   char **auth_mechanisms;
310   DBusList **auth_mechanisms_list;
311   int len;
312   
313   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
314
315   if (!_dbus_string_init (&full_address))
316     {
317       BUS_SET_OOM (error);
318       return NULL;
319     }
320
321   if (!server_data_slot_ref ())
322     {
323       BUS_SET_OOM (error);
324       _dbus_string_free (&full_address);
325       return NULL;
326     }
327   
328   parser = NULL;
329   context = NULL;
330   auth_mechanisms = NULL;
331   
332   parser = bus_config_load (config_file, error);
333   if (parser == NULL)
334     goto failed;
335   
336   context = dbus_new0 (BusContext, 1);
337   if (context == NULL)
338     {
339       BUS_SET_OOM (error);
340       goto failed;
341     }
342   
343   context->refcount = 1;
344
345   /* we need another ref of the server data slot for the context
346    * to own
347    */
348   if (!server_data_slot_ref ())
349     _dbus_assert_not_reached ("second ref of server data slot failed");
350   
351 #ifdef DBUS_BUILD_TESTS
352   context->activation_timeout = 6000;  /* 6 seconds */
353 #else
354   context->activation_timeout = 15000; /* 15 seconds */
355 #endif
356
357   /* Making this long risks making a DOS attack easier, but too short
358    * and legitimate auth will fail.  If interactive auth (ask user for
359    * password) is allowed, then potentially it has to be quite long.
360    * Ultimately it needs to come from the configuration file.
361    */     
362   context->auth_timeout = 3000; /* 3 seconds */
363
364   context->max_incomplete_connections = 32;
365   context->max_connections_per_user = 128;
366
367   /* Note that max_completed_connections / max_connections_per_user
368    * is the number of users that would have to work together to
369    * DOS all the other users.
370    */
371   context->max_completed_connections = 1024;
372   
373   context->loop = bus_loop_new ();
374   if (context->loop == NULL)
375     {
376       BUS_SET_OOM (error);
377       goto failed;
378     }
379   
380   /* Build an array of auth mechanisms */
381   
382   auth_mechanisms_list = bus_config_parser_get_mechanisms (parser);
383   len = _dbus_list_get_length (auth_mechanisms_list);
384
385   if (len > 0)
386     {
387       int i;
388
389       auth_mechanisms = dbus_new0 (char*, len + 1);
390       if (auth_mechanisms == NULL)
391         goto failed;
392       
393       i = 0;
394       link = _dbus_list_get_first_link (auth_mechanisms_list);
395       while (link != NULL)
396         {
397           auth_mechanisms[i] = _dbus_strdup (link->data);
398           if (auth_mechanisms[i] == NULL)
399             goto failed;
400           link = _dbus_list_get_next_link (auth_mechanisms_list, link);
401         }
402     }
403   else
404     {
405       auth_mechanisms = NULL;
406     }
407
408   /* Listen on our addresses */
409   
410   addresses = bus_config_parser_get_addresses (parser);  
411   
412   link = _dbus_list_get_first_link (addresses);
413   while (link != NULL)
414     {
415       DBusServer *server;
416       
417       server = dbus_server_listen (link->data, error);
418       if (server == NULL)
419         goto failed;
420       else if (!setup_server (context, server, auth_mechanisms, error))
421         goto failed;
422
423       if (!_dbus_list_append (&context->servers, server))
424         {
425           BUS_SET_OOM (error);
426           goto failed;
427         }          
428       
429       link = _dbus_list_get_next_link (addresses, link);
430     }
431
432   /* Here we change our credentials if required,
433    * as soon as we've set up our sockets
434    */
435   user = bus_config_parser_get_user (parser);
436   if (user != NULL)
437     {
438       DBusCredentials creds;
439       DBusString u;
440
441       _dbus_string_init_const (&u, user);
442
443       if (!_dbus_credentials_from_username (&u, &creds) ||
444           creds.uid < 0 ||
445           creds.gid < 0)
446         {
447           dbus_set_error (error, DBUS_ERROR_FAILED,
448                           "Could not get UID and GID for username \"%s\"",
449                           user);
450           goto failed;
451         }
452       
453       if (!_dbus_change_identity (creds.uid, creds.gid, error))
454         goto failed;
455     }
456
457   /* note that type may be NULL */
458   context->type = _dbus_strdup (bus_config_parser_get_type (parser));
459   
460   /* We have to build the address backward, so that
461    * <listen> later in the config file have priority
462    */
463   link = _dbus_list_get_last_link (&context->servers);
464   while (link != NULL)
465     {
466       char *addr;
467       
468       addr = dbus_server_get_address (link->data);
469       if (addr == NULL)
470         {
471           BUS_SET_OOM (error);
472           goto failed;
473         }
474
475       if (_dbus_string_get_length (&full_address) > 0)
476         {
477           if (!_dbus_string_append (&full_address, ";"))
478             {
479               BUS_SET_OOM (error);
480               goto failed;
481             }
482         }
483
484       if (!_dbus_string_append (&full_address, addr))
485         {
486           BUS_SET_OOM (error);
487           goto failed;
488         }
489
490       dbus_free (addr);
491
492       link = _dbus_list_get_prev_link (&context->servers, link);
493     }
494
495   if (!_dbus_string_copy_data (&full_address, &context->address))
496     {
497       BUS_SET_OOM (error);
498       goto failed;
499     }
500
501   /* Create activation subsystem */
502   
503   context->activation = bus_activation_new (context, &full_address,
504                                             bus_config_parser_get_service_dirs (parser),
505                                             error);
506   if (context->activation == NULL)
507     {
508       _DBUS_ASSERT_ERROR_IS_SET (error);
509       goto failed;
510     }
511
512   context->connections = bus_connections_new (context);
513   if (context->connections == NULL)
514     {
515       BUS_SET_OOM (error);
516       goto failed;
517     }
518
519   context->registry = bus_registry_new (context);
520   if (context->registry == NULL)
521     {
522       BUS_SET_OOM (error);
523       goto failed;
524     }
525   
526   context->rules_by_uid = _dbus_hash_table_new (DBUS_HASH_ULONG,
527                                                 NULL,
528                                                 free_rule_list_func);
529   if (context->rules_by_uid == NULL)
530     {
531       BUS_SET_OOM (error);
532       goto failed;
533     }
534
535   context->rules_by_gid = _dbus_hash_table_new (DBUS_HASH_ULONG,
536                                                 NULL,
537                                                 free_rule_list_func);
538   if (context->rules_by_gid == NULL)
539     {
540       BUS_SET_OOM (error);
541       goto failed;
542     }
543
544   /* Now become a daemon if appropriate */
545   if (bus_config_parser_get_fork (parser))
546     {
547       if (!_dbus_become_daemon (error))
548         goto failed;
549     }
550   
551   bus_config_parser_unref (parser);
552   _dbus_string_free (&full_address);
553   dbus_free_string_array (auth_mechanisms);
554   server_data_slot_unref ();
555   
556   return context;
557   
558  failed:  
559   if (parser != NULL)
560     bus_config_parser_unref (parser);
561
562   if (context != NULL)
563     bus_context_unref (context);
564
565   _dbus_string_free (&full_address);
566   dbus_free_string_array (auth_mechanisms);
567
568   server_data_slot_unref ();
569   
570   return NULL;
571 }
572
573 static void
574 shutdown_server (BusContext *context,
575                  DBusServer *server)
576 {
577   if (server == NULL ||
578       !dbus_server_get_is_connected (server))
579     return;
580   
581   if (!dbus_server_set_watch_functions (server,
582                                         NULL, NULL, NULL,
583                                         context,
584                                         NULL))
585     _dbus_assert_not_reached ("setting watch functions to NULL failed");
586   
587   if (!dbus_server_set_timeout_functions (server,
588                                           NULL, NULL, NULL,
589                                           context,
590                                           NULL))
591     _dbus_assert_not_reached ("setting timeout functions to NULL failed");
592   
593   dbus_server_disconnect (server);
594 }
595
596 void
597 bus_context_shutdown (BusContext  *context)
598 {
599   DBusList *link;
600
601   link = _dbus_list_get_first_link (&context->servers);
602   while (link != NULL)
603     {
604       shutdown_server (context, link->data);
605
606       link = _dbus_list_get_next_link (&context->servers, link);
607     }
608 }
609
610 void
611 bus_context_ref (BusContext *context)
612 {
613   _dbus_assert (context->refcount > 0);
614   context->refcount += 1;
615 }
616
617 void
618 bus_context_unref (BusContext *context)
619 {
620   _dbus_assert (context->refcount > 0);
621   context->refcount -= 1;
622
623   if (context->refcount == 0)
624     {
625       DBusList *link;
626       
627       _dbus_verbose ("Finalizing bus context %p\n", context);
628       
629       bus_context_shutdown (context);
630
631       if (context->connections)
632         {
633           bus_connections_unref (context->connections);
634           context->connections = NULL;
635         }
636       
637       if (context->registry)
638         {
639           bus_registry_unref (context->registry);
640           context->registry = NULL;
641         }
642       
643       if (context->activation)
644         {
645           bus_activation_unref (context->activation);
646           context->activation = NULL;
647         }
648
649       link = _dbus_list_get_first_link (&context->servers);
650       while (link != NULL)
651         {
652           dbus_server_unref (link->data);
653           
654           link = _dbus_list_get_next_link (&context->servers, link);
655         }
656       _dbus_list_clear (&context->servers);
657
658       if (context->rules_by_uid)
659         {
660           _dbus_hash_table_unref (context->rules_by_uid);
661           context->rules_by_uid = NULL;
662         }
663
664       if (context->rules_by_gid)
665         {
666           _dbus_hash_table_unref (context->rules_by_gid);
667           context->rules_by_gid = NULL;
668         }
669
670       if (context->loop)
671         {
672           bus_loop_unref (context->loop);
673           context->loop = NULL;
674         }
675       
676       dbus_free (context->type);
677       dbus_free (context->address);
678       dbus_free (context);
679
680       server_data_slot_unref ();
681     }
682 }
683
684 /* type may be NULL */
685 const char*
686 bus_context_get_type (BusContext *context)
687 {
688   return context->type;
689 }
690
691 const char*
692 bus_context_get_address (BusContext *context)
693 {
694   return context->address;
695 }
696
697 BusRegistry*
698 bus_context_get_registry (BusContext  *context)
699 {
700   return context->registry;
701 }
702
703 BusConnections*
704 bus_context_get_connections (BusContext  *context)
705 {
706   return context->connections;
707 }
708
709 BusActivation*
710 bus_context_get_activation (BusContext  *context)
711 {
712   return context->activation;
713 }
714
715 BusLoop*
716 bus_context_get_loop (BusContext *context)
717 {
718   return context->loop;
719 }
720
721 static dbus_bool_t
722 list_allows_user (dbus_bool_t           def,
723                   DBusList            **list,
724                   unsigned long         uid,
725                   const unsigned long  *group_ids,
726                   int                   n_group_ids)
727 {
728   DBusList *link;
729   dbus_bool_t allowed;
730   
731   allowed = def;
732
733   link = _dbus_list_get_first_link (list);
734   while (link != NULL)
735     {
736       BusPolicyRule *rule = link->data;
737       link = _dbus_list_get_next_link (list, link);
738       
739       if (rule->type == BUS_POLICY_RULE_USER)
740         {
741           if (rule->d.user.uid != uid)
742             continue;
743         }
744       else if (rule->type == BUS_POLICY_RULE_GROUP)
745         {
746           int i;
747
748           i = 0;
749           while (i < n_group_ids)
750             {
751               if (rule->d.group.gid == group_ids[i])
752                 break;
753               ++i;
754             }
755
756           if (i == n_group_ids)
757             continue;
758         }
759       else
760         continue;
761
762       allowed = rule->allow;
763     }
764   
765   return allowed;
766 }
767
768 dbus_bool_t
769 bus_context_allow_user (BusContext   *context,
770                         unsigned long uid)
771 {
772   dbus_bool_t allowed;
773   unsigned long *group_ids;
774   int n_group_ids;
775
776   /* On OOM or error we always reject the user */
777   if (!_dbus_get_groups (uid, &group_ids, &n_group_ids))
778     {
779       _dbus_verbose ("Did not get any groups for UID %lu\n",
780                      uid);
781       return FALSE;
782     }
783   
784   allowed = FALSE;
785
786   allowed = list_allows_user (allowed,
787                               &context->default_rules,
788                               uid,
789                               group_ids, n_group_ids);
790
791   allowed = list_allows_user (allowed,
792                               &context->mandatory_rules,
793                               uid,
794                               group_ids, n_group_ids);
795
796   dbus_free (group_ids);
797
798   return allowed;
799 }
800
801 static dbus_bool_t
802 add_list_to_policy (DBusList       **list,
803                     BusPolicy       *policy)
804 {
805   DBusList *link;
806
807   link = _dbus_list_get_first_link (list);
808   while (link != NULL)
809     {
810       BusPolicyRule *rule = link->data;
811       link = _dbus_list_get_next_link (list, link);
812
813       switch (rule->type)
814         {
815         case BUS_POLICY_RULE_USER:
816         case BUS_POLICY_RULE_GROUP:
817           /* These aren't per-connection policies */
818           break;
819
820         case BUS_POLICY_RULE_OWN:
821         case BUS_POLICY_RULE_SEND:
822         case BUS_POLICY_RULE_RECEIVE:
823           /* These are per-connection */
824           if (!bus_policy_append_rule (policy, rule))
825             return FALSE;
826           break;
827         }
828     }
829   
830   return TRUE;
831 }
832
833 BusPolicy*
834 bus_context_create_connection_policy (BusContext      *context,
835                                       DBusConnection  *connection)
836 {
837   BusPolicy *policy;
838   unsigned long uid;
839   DBusList **list;
840
841   _dbus_assert (dbus_connection_get_is_authenticated (connection));
842   
843   policy = bus_policy_new ();
844   if (policy == NULL)
845     return NULL;
846
847   if (!add_list_to_policy (&context->default_rules,
848                                       policy))
849     goto failed;
850
851   /* we avoid the overhead of looking up user's groups
852    * if we don't have any group rules anyway
853    */
854   if (_dbus_hash_table_get_n_entries (context->rules_by_gid) > 0)
855     {
856       const unsigned long *groups;
857       int n_groups;
858       int i;
859       
860       if (!bus_connection_get_groups (connection, &groups, &n_groups))
861         goto failed;
862       
863       i = 0;
864       while (i < n_groups)
865         {
866           list = _dbus_hash_table_lookup_ulong (context->rules_by_gid,
867                                                 groups[i]);
868           
869           if (list != NULL)
870             {
871               if (!add_list_to_policy (list, policy))
872                 goto failed;
873             }
874           
875           ++i;
876         }
877     }
878
879   if (!dbus_connection_get_unix_user (connection, &uid))
880     goto failed;
881
882   list = _dbus_hash_table_lookup_ulong (context->rules_by_uid,
883                                         uid);
884
885   if (!add_list_to_policy (list, policy))
886     goto failed;
887   
888   if (!add_list_to_policy (&context->mandatory_rules,
889                            policy))
890     goto failed;
891
892   bus_policy_optimize (policy);
893   
894   return policy;
895   
896  failed:
897   bus_policy_unref (policy);
898   return NULL;
899 }
900
901 int
902 bus_context_get_activation_timeout (BusContext *context)
903 {
904   
905   return context->activation_timeout;
906 }