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