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