2003-09-21 Havoc Pennington <hp@pobox.com>
[platform/upstream/dbus.git] / bus / policy.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* policy.c  Bus security policy
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 "policy.h"
25 #include "services.h"
26 #include "test.h"
27 #include "utils.h"
28 #include <dbus/dbus-list.h>
29 #include <dbus/dbus-hash.h>
30 #include <dbus/dbus-internals.h>
31
32 BusPolicyRule*
33 bus_policy_rule_new (BusPolicyRuleType type,
34                      dbus_bool_t       allow)
35 {
36   BusPolicyRule *rule;
37
38   rule = dbus_new0 (BusPolicyRule, 1);
39   if (rule == NULL)
40     return NULL;
41
42   rule->type = type;
43   rule->refcount = 1;
44   rule->allow = allow;
45
46   switch (rule->type)
47     {
48     case BUS_POLICY_RULE_USER:
49       rule->d.user.uid = DBUS_UID_UNSET;
50       break;
51     case BUS_POLICY_RULE_GROUP:
52       rule->d.group.gid = DBUS_GID_UNSET;
53       break;
54     case BUS_POLICY_RULE_SEND:
55       rule->d.send.message_type = DBUS_MESSAGE_TYPE_INVALID;
56       break;
57     case BUS_POLICY_RULE_RECEIVE:
58       rule->d.receive.message_type = DBUS_MESSAGE_TYPE_INVALID;
59       break;
60     case BUS_POLICY_RULE_OWN:
61       break;
62     }
63   
64   return rule;
65 }
66
67 void
68 bus_policy_rule_ref (BusPolicyRule *rule)
69 {
70   _dbus_assert (rule->refcount > 0);
71
72   rule->refcount += 1;
73 }
74
75 void
76 bus_policy_rule_unref (BusPolicyRule *rule)
77 {
78   _dbus_assert (rule->refcount > 0);
79
80   rule->refcount -= 1;
81   
82   if (rule->refcount == 0)
83     {
84       switch (rule->type)
85         {
86         case BUS_POLICY_RULE_SEND:
87           dbus_free (rule->d.send.path);
88           dbus_free (rule->d.send.interface);
89           dbus_free (rule->d.send.member);
90           dbus_free (rule->d.send.error);
91           dbus_free (rule->d.send.destination);
92           break;
93         case BUS_POLICY_RULE_RECEIVE:
94           dbus_free (rule->d.receive.path);
95           dbus_free (rule->d.receive.interface);
96           dbus_free (rule->d.receive.member);
97           dbus_free (rule->d.receive.error);
98           dbus_free (rule->d.receive.origin);
99           break;
100         case BUS_POLICY_RULE_OWN:
101           dbus_free (rule->d.own.service_name);
102           break;
103         case BUS_POLICY_RULE_USER:
104           break;
105         case BUS_POLICY_RULE_GROUP:
106           break;
107         }
108       
109       dbus_free (rule);
110     }
111 }
112
113 struct BusPolicy
114 {
115   int refcount;
116
117   DBusList *default_rules;       /**< Default policy rules */
118   DBusList *mandatory_rules;     /**< Mandatory policy rules */
119   DBusHashTable *rules_by_uid;   /**< per-UID policy rules */
120   DBusHashTable *rules_by_gid;   /**< per-GID policy rules */
121 };
122
123 static void
124 free_rule_func (void *data,
125                 void *user_data)
126 {
127   BusPolicyRule *rule = data;
128
129   bus_policy_rule_unref (rule);
130 }
131
132 static void
133 free_rule_list_func (void *data)
134 {
135   DBusList **list = data;
136
137   if (list == NULL) /* DBusHashTable is on crack */
138     return;
139   
140   _dbus_list_foreach (list, free_rule_func, NULL);
141   
142   _dbus_list_clear (list);
143
144   dbus_free (list);
145 }
146
147 BusPolicy*
148 bus_policy_new (void)
149 {
150   BusPolicy *policy;
151
152   policy = dbus_new0 (BusPolicy, 1);
153   if (policy == NULL)
154     return NULL;
155
156   policy->refcount = 1;
157   
158   policy->rules_by_uid = _dbus_hash_table_new (DBUS_HASH_ULONG,
159                                                NULL,
160                                                free_rule_list_func);
161   if (policy->rules_by_uid == NULL)
162     goto failed;
163
164   policy->rules_by_gid = _dbus_hash_table_new (DBUS_HASH_ULONG,
165                                                NULL,
166                                                free_rule_list_func);
167   if (policy->rules_by_gid == NULL)
168     goto failed;
169   
170   return policy;
171   
172  failed:
173   bus_policy_unref (policy);
174   return NULL;
175 }
176
177 void
178 bus_policy_ref (BusPolicy *policy)
179 {
180   _dbus_assert (policy->refcount > 0);
181
182   policy->refcount += 1;
183 }
184
185 void
186 bus_policy_unref (BusPolicy *policy)
187 {
188   _dbus_assert (policy->refcount > 0);
189
190   policy->refcount -= 1;
191
192   if (policy->refcount == 0)
193     {
194       _dbus_list_foreach (&policy->default_rules, free_rule_func, NULL);
195       _dbus_list_clear (&policy->default_rules);
196
197       _dbus_list_foreach (&policy->mandatory_rules, free_rule_func, NULL);
198       _dbus_list_clear (&policy->mandatory_rules);
199       
200       if (policy->rules_by_uid)
201         {
202           _dbus_hash_table_unref (policy->rules_by_uid);
203           policy->rules_by_uid = NULL;
204         }
205
206       if (policy->rules_by_gid)
207         {
208           _dbus_hash_table_unref (policy->rules_by_gid);
209           policy->rules_by_gid = NULL;
210         }
211       
212       dbus_free (policy);
213     }
214 }
215
216 static dbus_bool_t
217 add_list_to_client (DBusList        **list,
218                     BusClientPolicy  *client)
219 {
220   DBusList *link;
221
222   link = _dbus_list_get_first_link (list);
223   while (link != NULL)
224     {
225       BusPolicyRule *rule = link->data;
226       link = _dbus_list_get_next_link (list, link);
227
228       switch (rule->type)
229         {
230         case BUS_POLICY_RULE_USER:
231         case BUS_POLICY_RULE_GROUP:
232           /* These aren't per-connection policies */
233           break;
234
235         case BUS_POLICY_RULE_OWN:
236         case BUS_POLICY_RULE_SEND:
237         case BUS_POLICY_RULE_RECEIVE:
238           /* These are per-connection */
239           if (!bus_client_policy_append_rule (client, rule))
240             return FALSE;
241           break;
242         }
243     }
244   
245   return TRUE;
246 }
247
248 BusClientPolicy*
249 bus_policy_create_client_policy (BusPolicy      *policy,
250                                  DBusConnection *connection,
251                                  DBusError      *error)
252 {
253   BusClientPolicy *client;
254   unsigned long uid;
255
256   _dbus_assert (dbus_connection_get_is_authenticated (connection));
257   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
258   
259   client = bus_client_policy_new ();
260   if (client == NULL)
261     goto nomem;
262
263   if (!add_list_to_client (&policy->default_rules,
264                            client))
265     goto nomem;
266
267   /* we avoid the overhead of looking up user's groups
268    * if we don't have any group rules anyway
269    */
270   if (_dbus_hash_table_get_n_entries (policy->rules_by_gid) > 0)
271     {
272       unsigned long *groups;
273       int n_groups;
274       int i;
275       
276       if (!bus_connection_get_groups (connection, &groups, &n_groups, error))
277         goto failed;
278       
279       i = 0;
280       while (i < n_groups)
281         {
282           DBusList **list;
283           
284           list = _dbus_hash_table_lookup_ulong (policy->rules_by_gid,
285                                                 groups[i]);
286           
287           if (list != NULL)
288             {
289               if (!add_list_to_client (list, client))
290                 {
291                   dbus_free (groups);
292                   goto nomem;
293                 }
294             }
295           
296           ++i;
297         }
298
299       dbus_free (groups);
300     }
301
302   if (!dbus_connection_get_unix_user (connection, &uid))
303     {
304       dbus_set_error (error, DBUS_ERROR_FAILED,
305                       "No user ID known for connection, cannot determine security policy\n");
306       goto failed;
307     }
308
309   if (_dbus_hash_table_get_n_entries (policy->rules_by_uid) > 0)
310     {
311       DBusList **list;
312       
313       list = _dbus_hash_table_lookup_ulong (policy->rules_by_uid,
314                                             uid);
315
316       if (list != NULL)
317         {
318           if (!add_list_to_client (list, client))
319             goto nomem;
320         }
321     }
322
323   if (!add_list_to_client (&policy->mandatory_rules,
324                            client))
325     goto nomem;
326
327   bus_client_policy_optimize (client);
328   
329   return client;
330
331  nomem:
332   BUS_SET_OOM (error);
333  failed:
334   _DBUS_ASSERT_ERROR_IS_SET (error);
335   if (client)
336     bus_client_policy_unref (client);
337   return NULL;
338 }
339
340 static dbus_bool_t
341 list_allows_user (dbus_bool_t           def,
342                   DBusList            **list,
343                   unsigned long         uid,
344                   const unsigned long  *group_ids,
345                   int                   n_group_ids)
346 {
347   DBusList *link;
348   dbus_bool_t allowed;
349   
350   allowed = def;
351
352   link = _dbus_list_get_first_link (list);
353   while (link != NULL)
354     {
355       BusPolicyRule *rule = link->data;
356       link = _dbus_list_get_next_link (list, link);
357       
358       if (rule->type == BUS_POLICY_RULE_USER)
359         {
360           _dbus_verbose ("List %p user rule uid="DBUS_UID_FORMAT"\n",
361                          list, rule->d.user.uid);
362           
363           if (rule->d.user.uid == DBUS_UID_UNSET)
364             ; /* '*' wildcard */
365           else if (rule->d.user.uid != uid)
366             continue;
367         }
368       else if (rule->type == BUS_POLICY_RULE_GROUP)
369         {
370           _dbus_verbose ("List %p group rule uid="DBUS_UID_FORMAT"\n",
371                          list, rule->d.user.uid);
372           
373           if (rule->d.group.gid == DBUS_GID_UNSET)
374             ;  /* '*' wildcard */
375           else
376             {
377               int i;
378               
379               i = 0;
380               while (i < n_group_ids)
381                 {
382                   if (rule->d.group.gid == group_ids[i])
383                     break;
384                   ++i;
385                 }
386               
387               if (i == n_group_ids)
388                 continue;
389             }
390         }
391       else
392         continue;
393
394       allowed = rule->allow;
395     }
396   
397   return allowed;
398 }
399
400 dbus_bool_t
401 bus_policy_allow_user (BusPolicy        *policy,
402                        DBusUserDatabase *user_database,
403                        unsigned long     uid)
404 {
405   dbus_bool_t allowed;
406   unsigned long *group_ids;
407   int n_group_ids;
408
409   /* On OOM or error we always reject the user */
410   if (!_dbus_user_database_get_groups (user_database,
411                                        uid, &group_ids, &n_group_ids, NULL))
412     {
413       _dbus_verbose ("Did not get any groups for UID %lu\n",
414                      uid);
415       return FALSE;
416     }
417   
418   allowed = FALSE;
419
420   allowed = list_allows_user (allowed,
421                               &policy->default_rules,
422                               uid,
423                               group_ids, n_group_ids);
424
425   allowed = list_allows_user (allowed,
426                               &policy->mandatory_rules,
427                               uid,
428                               group_ids, n_group_ids);
429
430   dbus_free (group_ids);
431
432   _dbus_verbose ("UID %lu allowed = %d\n", uid, allowed);
433   
434   return allowed;
435 }
436
437 dbus_bool_t
438 bus_policy_append_default_rule (BusPolicy      *policy,
439                                 BusPolicyRule  *rule)
440 {
441   if (!_dbus_list_append (&policy->default_rules, rule))
442     return FALSE;
443
444   bus_policy_rule_ref (rule);
445
446   return TRUE;
447 }
448
449 dbus_bool_t
450 bus_policy_append_mandatory_rule (BusPolicy      *policy,
451                                   BusPolicyRule  *rule)
452 {
453   if (!_dbus_list_append (&policy->mandatory_rules, rule))
454     return FALSE;
455
456   bus_policy_rule_ref (rule);
457
458   return TRUE;
459 }
460
461 static DBusList**
462 get_list (DBusHashTable *hash,
463           unsigned long  key)
464 {
465   DBusList **list;
466
467   list = _dbus_hash_table_lookup_ulong (hash, key);
468
469   if (list == NULL)
470     {
471       list = dbus_new0 (DBusList*, 1);
472       if (list == NULL)
473         return NULL;
474
475       if (!_dbus_hash_table_insert_ulong (hash, key, list))
476         {
477           dbus_free (list);
478           return NULL;
479         }
480     }
481
482   return list;
483 }
484
485 dbus_bool_t
486 bus_policy_append_user_rule (BusPolicy      *policy,
487                              dbus_uid_t      uid,
488                              BusPolicyRule  *rule)
489 {
490   DBusList **list;
491
492   list = get_list (policy->rules_by_uid, uid);
493
494   if (list == NULL)
495     return FALSE;
496
497   if (!_dbus_list_append (list, rule))
498     return FALSE;
499
500   bus_policy_rule_ref (rule);
501
502   return TRUE;
503 }
504
505 dbus_bool_t
506 bus_policy_append_group_rule (BusPolicy      *policy,
507                               dbus_gid_t      gid,
508                               BusPolicyRule  *rule)
509 {
510   DBusList **list;
511
512   list = get_list (policy->rules_by_gid, gid);
513
514   if (list == NULL)
515     return FALSE;
516
517   if (!_dbus_list_append (list, rule))
518     return FALSE;
519
520   bus_policy_rule_ref (rule);
521
522   return TRUE;
523 }
524
525 static dbus_bool_t
526 append_copy_of_policy_list (DBusList **list,
527                             DBusList **to_append)
528 {
529   DBusList *link;
530   DBusList *tmp_list;
531
532   tmp_list = NULL;
533
534   /* Preallocate all our links */
535   link = _dbus_list_get_first_link (to_append);
536   while (link != NULL)
537     {
538       if (!_dbus_list_append (&tmp_list, link->data))
539         {
540           _dbus_list_clear (&tmp_list);
541           return FALSE;
542         }
543       
544       link = _dbus_list_get_next_link (to_append, link);
545     }
546
547   /* Now append them */
548   while ((link = _dbus_list_pop_first_link (&tmp_list)))
549     {
550       bus_policy_rule_ref (link->data);
551       _dbus_list_append_link (list, link);
552     }
553
554   return TRUE;
555 }
556
557 static dbus_bool_t
558 merge_id_hash (DBusHashTable *dest,
559                DBusHashTable *to_absorb)
560 {
561   DBusHashIter iter;
562   
563   _dbus_hash_iter_init (to_absorb, &iter);
564   while (_dbus_hash_iter_next (&iter))
565     {
566       unsigned long id = _dbus_hash_iter_get_ulong_key (&iter);
567       DBusList **list = _dbus_hash_iter_get_value (&iter);
568       DBusList **target = get_list (dest, id);
569
570       if (target == NULL)
571         return FALSE;
572
573       if (!append_copy_of_policy_list (target, list))
574         return FALSE;
575     }
576
577   return TRUE;
578 }
579
580 dbus_bool_t
581 bus_policy_merge (BusPolicy *policy,
582                   BusPolicy *to_absorb)
583 {
584   /* Not properly atomic, but as used for configuration files
585    * we don't rely on it.
586    */  
587   if (!append_copy_of_policy_list (&policy->default_rules,
588                                    &to_absorb->default_rules))
589     return FALSE;
590   
591   if (!append_copy_of_policy_list (&policy->mandatory_rules,
592                                    &to_absorb->mandatory_rules))
593     return FALSE;
594
595   if (!merge_id_hash (policy->rules_by_uid,
596                       to_absorb->rules_by_uid))
597     return FALSE;
598   
599   if (!merge_id_hash (policy->rules_by_gid,
600                       to_absorb->rules_by_gid))
601     return FALSE;
602
603   return TRUE;
604 }
605
606 struct BusClientPolicy
607 {
608   int refcount;
609
610   DBusList *rules;
611 };
612
613 BusClientPolicy*
614 bus_client_policy_new (void)
615 {
616   BusClientPolicy *policy;
617
618   policy = dbus_new0 (BusClientPolicy, 1);
619   if (policy == NULL)
620     return NULL;
621
622   policy->refcount = 1;
623
624   return policy;
625 }
626
627 void
628 bus_client_policy_ref (BusClientPolicy *policy)
629 {
630   _dbus_assert (policy->refcount > 0);
631
632   policy->refcount += 1;
633 }
634
635 static void
636 rule_unref_foreach (void *data,
637                     void *user_data)
638 {
639   BusPolicyRule *rule = data;
640
641   bus_policy_rule_unref (rule);
642 }
643
644 void
645 bus_client_policy_unref (BusClientPolicy *policy)
646 {
647   _dbus_assert (policy->refcount > 0);
648
649   policy->refcount -= 1;
650
651   if (policy->refcount == 0)
652     {
653       _dbus_list_foreach (&policy->rules,
654                           rule_unref_foreach,
655                           NULL);
656
657       _dbus_list_clear (&policy->rules);
658       
659       dbus_free (policy);
660     }
661 }
662
663 static void
664 remove_rules_by_type_up_to (BusClientPolicy   *policy,
665                             BusPolicyRuleType  type,
666                             DBusList          *up_to)
667 {
668   DBusList *link;
669
670   link = _dbus_list_get_first_link (&policy->rules);
671   while (link != up_to)
672     {
673       BusPolicyRule *rule = link->data;
674       DBusList *next = _dbus_list_get_next_link (&policy->rules, link);
675
676       if (rule->type == type)
677         {
678           _dbus_list_remove_link (&policy->rules, link);
679           bus_policy_rule_unref (rule);
680         }
681       
682       link = next;
683     }
684 }
685
686 void
687 bus_client_policy_optimize (BusClientPolicy *policy)
688 {
689   DBusList *link;
690
691   /* The idea here is that if we have:
692    * 
693    * <allow send_interface="foo.bar"/>
694    * <deny send_interface="*"/>
695    *
696    * (for example) the deny will always override the allow.  So we
697    * delete the allow. Ditto for deny followed by allow, etc. This is
698    * a dumb thing to put in a config file, but the <include> feature
699    * of files allows for an "inheritance and override" pattern where
700    * it could make sense. If an included file wants to "start over"
701    * with a blanket deny, no point keeping the rules from the parent
702    * file.
703    */
704
705   _dbus_verbose ("Optimizing policy with %d rules\n",
706                  _dbus_list_get_length (&policy->rules));
707   
708   link = _dbus_list_get_first_link (&policy->rules);
709   while (link != NULL)
710     {
711       BusPolicyRule *rule;
712       DBusList *next;
713       dbus_bool_t remove_preceding;
714
715       next = _dbus_list_get_next_link (&policy->rules, link);
716       rule = link->data;
717       
718       remove_preceding = FALSE;
719
720       _dbus_assert (rule != NULL);
721       
722       switch (rule->type)
723         {
724         case BUS_POLICY_RULE_SEND:
725           remove_preceding =
726             rule->d.send.message_type == DBUS_MESSAGE_TYPE_INVALID &&
727             rule->d.send.path == NULL &&
728             rule->d.send.interface == NULL &&
729             rule->d.send.member == NULL &&
730             rule->d.send.error == NULL &&
731             rule->d.send.destination == NULL;
732           break;
733         case BUS_POLICY_RULE_RECEIVE:
734           remove_preceding =
735             rule->d.receive.message_type == DBUS_MESSAGE_TYPE_INVALID &&
736             rule->d.receive.path == NULL &&
737             rule->d.receive.interface == NULL &&
738             rule->d.receive.member == NULL &&
739             rule->d.receive.error == NULL &&
740             rule->d.receive.origin == NULL;
741           break;
742         case BUS_POLICY_RULE_OWN:
743           remove_preceding =
744             rule->d.own.service_name == NULL;
745           break;
746         case BUS_POLICY_RULE_USER:
747         case BUS_POLICY_RULE_GROUP:
748           _dbus_assert_not_reached ("invalid rule");
749           break;
750         }
751
752       if (remove_preceding)
753         remove_rules_by_type_up_to (policy, rule->type,
754                                     link);
755       
756       link = next;
757     }
758
759   _dbus_verbose ("After optimization, policy has %d rules\n",
760                  _dbus_list_get_length (&policy->rules));
761 }
762
763 dbus_bool_t
764 bus_client_policy_append_rule (BusClientPolicy *policy,
765                                BusPolicyRule   *rule)
766 {
767   _dbus_verbose ("Appending rule %p with type %d to policy %p\n",
768                  rule, rule->type, policy);
769   
770   if (!_dbus_list_append (&policy->rules, rule))
771     return FALSE;
772
773   bus_policy_rule_ref (rule);
774
775   return TRUE;
776 }
777
778 dbus_bool_t
779 bus_client_policy_check_can_send (BusClientPolicy *policy,
780                                   BusRegistry     *registry,
781                                   DBusConnection  *receiver,
782                                   DBusMessage     *message)
783 {
784   DBusList *link;
785   dbus_bool_t allowed;
786   
787   /* policy->rules is in the order the rules appeared
788    * in the config file, i.e. last rule that applies wins
789    */
790
791   _dbus_verbose ("  (policy) checking send rules\n");
792   
793   allowed = FALSE;
794   link = _dbus_list_get_first_link (&policy->rules);
795   while (link != NULL)
796     {
797       BusPolicyRule *rule = link->data;
798
799       link = _dbus_list_get_next_link (&policy->rules, link);
800       
801       /* Rule is skipped if it specifies a different
802        * message name from the message, or a different
803        * destination from the message
804        */
805       
806       if (rule->type != BUS_POLICY_RULE_SEND)
807         {
808           _dbus_verbose ("  (policy) skipping non-send rule\n");
809           continue;
810         }
811
812       if (rule->d.send.message_type != DBUS_MESSAGE_TYPE_INVALID)
813         {
814           if (dbus_message_get_type (message) != rule->d.send.message_type)
815             {
816               _dbus_verbose ("  (policy) skipping rule for different message type\n");
817               continue;
818             }
819         }
820       
821       if (rule->d.send.path != NULL)
822         {
823           if (dbus_message_get_path (message) != NULL &&
824               strcmp (dbus_message_get_path (message),
825                       rule->d.send.path) != 0)
826             {
827               _dbus_verbose ("  (policy) skipping rule for different path\n");
828               continue;
829             }
830         }
831       
832       if (rule->d.send.interface != NULL)
833         {
834           if (dbus_message_get_interface (message) != NULL &&
835               strcmp (dbus_message_get_interface (message),
836                       rule->d.send.interface) != 0)
837             {
838               _dbus_verbose ("  (policy) skipping rule for different interface\n");
839               continue;
840             }
841         }
842
843       if (rule->d.send.member != NULL)
844         {
845           if (dbus_message_get_member (message) != NULL &&
846               strcmp (dbus_message_get_member (message),
847                       rule->d.send.member) != 0)
848             {
849               _dbus_verbose ("  (policy) skipping rule for different member\n");
850               continue;
851             }
852         }
853
854       if (rule->d.send.error != NULL)
855         {
856           if (dbus_message_get_error_name (message) != NULL &&
857               strcmp (dbus_message_get_error_name (message),
858                       rule->d.send.error) != 0)
859             {
860               _dbus_verbose ("  (policy) skipping rule for different error name\n");
861               continue;
862             }
863         }
864       
865       if (rule->d.send.destination != NULL)
866         {
867           /* receiver can be NULL for messages that are sent to the
868            * message bus itself, we check the strings in that case as
869            * built-in services don't have a DBusConnection but messages
870            * to them have a destination service name.
871            */
872           if (receiver == NULL)
873             {
874               if (!dbus_message_has_destination (message,
875                                                  rule->d.send.destination))
876                 {
877                   _dbus_verbose ("  (policy) skipping rule because message dest is not %s\n",
878                                  rule->d.send.destination);
879                   continue;
880                 }
881             }
882           else
883             {
884               DBusString str;
885               BusService *service;
886               
887               _dbus_string_init_const (&str, rule->d.send.destination);
888               
889               service = bus_registry_lookup (registry, &str);
890               if (service == NULL)
891                 {
892                   _dbus_verbose ("  (policy) skipping rule because dest %s doesn't exist\n",
893                                  rule->d.send.destination);
894                   continue;
895                 }
896
897               if (!bus_service_has_owner (service, receiver))
898                 {
899                   _dbus_verbose ("  (policy) skipping rule because dest %s isn't owned by receiver\n",
900                                  rule->d.send.destination);
901                   continue;
902                 }
903             }
904         }
905
906       /* Use this rule */
907       allowed = rule->allow;
908
909       _dbus_verbose ("  (policy) used rule, allow now = %d\n",
910                      allowed);
911     }
912
913   return allowed;
914 }
915
916 dbus_bool_t
917 bus_client_policy_check_can_receive (BusClientPolicy *policy,
918                                      BusRegistry     *registry,
919                                      DBusConnection  *sender,
920                                      DBusConnection  *addressed_recipient,
921                                      DBusConnection  *proposed_recipient,
922                                      DBusMessage     *message)
923 {
924   DBusList *link;
925   dbus_bool_t allowed;
926   dbus_bool_t eavesdropping;
927   
928   /* NULL sender, proposed_recipient means the bus driver.  NULL
929    * addressed_recipient means the message didn't specify an explicit
930    * target. If proposed_recipient is NULL, then addressed_recipient
931    * is also NULL but is implicitly the bus driver.
932    */
933
934   _dbus_assert (proposed_recipient == NULL ||
935                 (dbus_message_get_destination (message) == NULL ||
936                  addressed_recipient != NULL));
937   
938   eavesdropping =
939     (proposed_recipient == NULL || /* explicitly to bus driver */
940      (addressed_recipient && addressed_recipient != proposed_recipient)); /* explicitly to a different recipient */
941   
942   /* policy->rules is in the order the rules appeared
943    * in the config file, i.e. last rule that applies wins
944    */
945
946   _dbus_verbose ("  (policy) checking receive rules, eavesdropping = %d\n", eavesdropping);
947   
948   allowed = FALSE;
949   link = _dbus_list_get_first_link (&policy->rules);
950   while (link != NULL)
951     {
952       BusPolicyRule *rule = link->data;
953
954       link = _dbus_list_get_next_link (&policy->rules, link);      
955       
956       if (rule->type != BUS_POLICY_RULE_RECEIVE)
957         {
958           _dbus_verbose ("  (policy) skipping non-receive rule\n");
959           continue;
960         }
961
962       if (rule->d.receive.message_type != DBUS_MESSAGE_TYPE_INVALID)
963         {
964           if (dbus_message_get_type (message) != rule->d.receive.message_type)
965             {
966               _dbus_verbose ("  (policy) skipping rule for different message type\n");
967               continue;
968             }
969         }
970
971       /* for allow, eavesdrop=false means the rule doesn't apply when
972        * eavesdropping. eavesdrop=true means always allow.
973        */
974       if (eavesdropping && rule->allow && !rule->d.receive.eavesdrop)
975         {
976           _dbus_verbose ("  (policy) skipping allow rule since it doesn't apply to eavesdropping\n");
977           continue;
978         }
979
980       /* for deny, eavesdrop=true means the rule applies only when
981        * eavesdropping; eavesdrop=false means always deny.
982        */
983       if (!eavesdropping && !rule->allow && rule->d.receive.eavesdrop)
984         {
985           _dbus_verbose ("  (policy) skipping deny rule since it only applies to eavesdropping\n");
986           continue;
987         }
988       
989       if (rule->d.receive.path != NULL)
990         {
991           if (dbus_message_get_path (message) != NULL &&
992               strcmp (dbus_message_get_path (message),
993                       rule->d.receive.path) != 0)
994             {
995               _dbus_verbose ("  (policy) skipping rule for different path\n");
996               continue;
997             }
998         }
999       
1000       if (rule->d.receive.interface != NULL)
1001         {
1002           if (dbus_message_get_interface (message) != NULL &&
1003               strcmp (dbus_message_get_interface (message),
1004                       rule->d.receive.interface) != 0)
1005             {
1006               _dbus_verbose ("  (policy) skipping rule for different interface\n");
1007               continue;
1008             }
1009         }      
1010
1011       if (rule->d.receive.member != NULL)
1012         {
1013           if (dbus_message_get_member (message) != NULL &&
1014               strcmp (dbus_message_get_member (message),
1015                       rule->d.receive.member) != 0)
1016             {
1017               _dbus_verbose ("  (policy) skipping rule for different member\n");
1018               continue;
1019             }
1020         }
1021
1022       if (rule->d.receive.error != NULL)
1023         {
1024           if (dbus_message_get_error_name (message) != NULL &&
1025               strcmp (dbus_message_get_error_name (message),
1026                       rule->d.receive.error) != 0)
1027             {
1028               _dbus_verbose ("  (policy) skipping rule for different error name\n");
1029               continue;
1030             }
1031         }
1032       
1033       if (rule->d.receive.origin != NULL)
1034         {          
1035           /* sender can be NULL for messages that originate from the
1036            * message bus itself, we check the strings in that case as
1037            * built-in services don't have a DBusConnection but will
1038            * still set the sender on their messages.
1039            */
1040           if (sender == NULL)
1041             {
1042               if (!dbus_message_has_sender (message,
1043                                             rule->d.receive.origin))
1044                 {
1045                   _dbus_verbose ("  (policy) skipping rule because message sender is not %s\n",
1046                                  rule->d.receive.origin);
1047                   continue;
1048                 }
1049             }
1050           else
1051             {
1052               BusService *service;
1053               DBusString str;
1054
1055               _dbus_string_init_const (&str, rule->d.receive.origin);
1056               
1057               service = bus_registry_lookup (registry, &str);
1058               
1059               if (service == NULL)
1060                 {
1061                   _dbus_verbose ("  (policy) skipping rule because origin %s doesn't exist\n",
1062                                  rule->d.receive.origin);
1063                   continue;
1064                 }
1065
1066               if (!bus_service_has_owner (service, sender))
1067                 {
1068                   _dbus_verbose ("  (policy) skipping rule because origin %s isn't owned by sender\n",
1069                                  rule->d.receive.origin);
1070                   continue;
1071                 }
1072             }
1073         }
1074       
1075       /* Use this rule */
1076       allowed = rule->allow;
1077
1078       _dbus_verbose ("  (policy) used rule, allow now = %d\n",
1079                      allowed);
1080     }
1081
1082   return allowed;
1083 }
1084
1085 dbus_bool_t
1086 bus_client_policy_check_can_own (BusClientPolicy  *policy,
1087                                  DBusConnection   *connection,
1088                                  const DBusString *service_name)
1089 {
1090   DBusList *link;
1091   dbus_bool_t allowed;
1092   
1093   /* policy->rules is in the order the rules appeared
1094    * in the config file, i.e. last rule that applies wins
1095    */
1096
1097   allowed = FALSE;
1098   link = _dbus_list_get_first_link (&policy->rules);
1099   while (link != NULL)
1100     {
1101       BusPolicyRule *rule = link->data;
1102
1103       link = _dbus_list_get_next_link (&policy->rules, link);
1104       
1105       /* Rule is skipped if it specifies a different service name from
1106        * the desired one.
1107        */
1108       
1109       if (rule->type != BUS_POLICY_RULE_OWN)
1110         continue;
1111
1112       if (rule->d.own.service_name != NULL)
1113         {
1114           if (!_dbus_string_equal_c_str (service_name,
1115                                          rule->d.own.service_name))
1116             continue;
1117         }
1118
1119       /* Use this rule */
1120       allowed = rule->allow;
1121     }
1122
1123   return allowed;
1124 }
1125
1126 #ifdef DBUS_BUILD_TESTS
1127
1128 dbus_bool_t
1129 bus_policy_test (const DBusString *test_data_dir)
1130 {
1131   /* This doesn't do anything for now because I decided to do it in
1132    * dispatch.c instead by having some of the clients in dispatch.c
1133    * have particular policies applied to them.
1134    */
1135   
1136   return TRUE;
1137 }
1138
1139 #endif /* DBUS_BUILD_TESTS */