2003-08-17 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_has_interface (message,
805                                            rule->d.send.interface))
806             {
807               _dbus_verbose ("  (policy) skipping rule for different interface\n");
808               continue;
809             }
810         }
811       else if (rule->d.send.member != NULL)
812         {
813           if (!dbus_message_has_member (message,
814                                         rule->d.send.member))
815             {
816               _dbus_verbose ("  (policy) skipping rule for different member\n");
817               continue;
818             }
819         }
820       else if (rule->d.send.error != NULL)
821         {
822           if (!dbus_message_has_error_name (message,
823                                             rule->d.send.error))
824             {
825               _dbus_verbose ("  (policy) skipping rule for different error name\n");
826               continue;
827             }
828         }
829       
830       if (rule->d.send.destination != NULL)
831         {
832           /* receiver can be NULL for messages that are sent to the
833            * message bus itself, we check the strings in that case as
834            * built-in services don't have a DBusConnection but messages
835            * to them have a destination service name.
836            */
837           if (receiver == NULL)
838             {
839               if (!dbus_message_has_destination (message,
840                                                  rule->d.send.destination))
841                 {
842                   _dbus_verbose ("  (policy) skipping rule because message dest is not %s\n",
843                                  rule->d.send.destination);
844                   continue;
845                 }
846             }
847           else
848             {
849               DBusString str;
850               BusService *service;
851               
852               _dbus_string_init_const (&str, rule->d.send.destination);
853               
854               service = bus_registry_lookup (registry, &str);
855               if (service == NULL)
856                 {
857                   _dbus_verbose ("  (policy) skipping rule because dest %s doesn't exist\n",
858                                  rule->d.send.destination);
859                   continue;
860                 }
861
862               if (!bus_service_has_owner (service, receiver))
863                 {
864                   _dbus_verbose ("  (policy) skipping rule because dest %s isn't owned by receiver\n",
865                                  rule->d.send.destination);
866                   continue;
867                 }
868             }
869         }
870
871       /* Use this rule */
872       allowed = rule->allow;
873
874       _dbus_verbose ("  (policy) used rule, allow now = %d\n",
875                      allowed);
876     }
877
878   return allowed;
879 }
880
881 dbus_bool_t
882 bus_client_policy_check_can_receive (BusClientPolicy *policy,
883                                      BusRegistry     *registry,
884                                      DBusConnection  *sender,
885                                      DBusMessage     *message)
886 {
887   DBusList *link;
888   dbus_bool_t allowed;
889   
890   /* policy->rules is in the order the rules appeared
891    * in the config file, i.e. last rule that applies wins
892    */
893
894   _dbus_verbose ("  (policy) checking receive rules\n");
895   
896   allowed = FALSE;
897   link = _dbus_list_get_first_link (&policy->rules);
898   while (link != NULL)
899     {
900       BusPolicyRule *rule = link->data;
901
902       link = _dbus_list_get_next_link (&policy->rules, link);
903       
904       /* Rule is skipped if it specifies a different
905        * message name from the message, or a different
906        * origin from the message
907        */
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_has_interface (message,
918                                            rule->d.receive.interface))
919             {
920               _dbus_verbose ("  (policy) skipping rule for different interface\n");
921               continue;
922             }
923         }
924       else if (rule->d.receive.member != NULL)
925         {
926           if (!dbus_message_has_member (message,
927                                         rule->d.receive.member))
928             {
929               _dbus_verbose ("  (policy) skipping rule for different member\n");
930               continue;
931             }
932         }
933       else if (rule->d.receive.error != NULL)
934         {
935           if (!dbus_message_has_error_name (message,
936                                             rule->d.receive.error))
937             {
938               _dbus_verbose ("  (policy) skipping rule for different error name\n");
939               continue;
940             }
941         }
942       
943       if (rule->d.receive.origin != NULL)
944         {          
945           /* sender can be NULL for messages that originate from the
946            * message bus itself, we check the strings in that case as
947            * built-in services don't have a DBusConnection but will
948            * still set the sender on their messages.
949            */
950           if (sender == NULL)
951             {
952               if (!dbus_message_has_sender (message,
953                                             rule->d.receive.origin))
954                 {
955                   _dbus_verbose ("  (policy) skipping rule because message sender is not %s\n",
956                                  rule->d.receive.origin);
957                   continue;
958                 }
959             }
960           else
961             {
962               BusService *service;
963               DBusString str;
964
965               _dbus_string_init_const (&str, rule->d.receive.origin);
966               
967               service = bus_registry_lookup (registry, &str);
968               
969               if (service == NULL)
970                 {
971                   _dbus_verbose ("  (policy) skipping rule because origin %s doesn't exist\n",
972                                  rule->d.receive.origin);
973                   continue;
974                 }
975
976               if (!bus_service_has_owner (service, sender))
977                 {
978                   _dbus_verbose ("  (policy) skipping rule because origin %s isn't owned by sender\n",
979                                  rule->d.receive.origin);
980                   continue;
981                 }
982             }
983         }
984
985       /* Use this rule */
986       allowed = rule->allow;
987
988       _dbus_verbose ("  (policy) used rule, allow now = %d\n",
989                      allowed);
990     }
991
992   return allowed;
993 }
994
995 dbus_bool_t
996 bus_client_policy_check_can_own (BusClientPolicy  *policy,
997                                  DBusConnection   *connection,
998                                  const DBusString *service_name)
999 {
1000   DBusList *link;
1001   dbus_bool_t allowed;
1002   
1003   /* policy->rules is in the order the rules appeared
1004    * in the config file, i.e. last rule that applies wins
1005    */
1006
1007   allowed = FALSE;
1008   link = _dbus_list_get_first_link (&policy->rules);
1009   while (link != NULL)
1010     {
1011       BusPolicyRule *rule = link->data;
1012
1013       link = _dbus_list_get_next_link (&policy->rules, link);
1014       
1015       /* Rule is skipped if it specifies a different service name from
1016        * the desired one.
1017        */
1018       
1019       if (rule->type != BUS_POLICY_RULE_OWN)
1020         continue;
1021
1022       if (rule->d.own.service_name != NULL)
1023         {
1024           if (!_dbus_string_equal_c_str (service_name,
1025                                          rule->d.own.service_name))
1026             continue;
1027         }
1028
1029       /* Use this rule */
1030       allowed = rule->allow;
1031     }
1032
1033   return allowed;
1034 }
1035
1036 #ifdef DBUS_BUILD_TESTS
1037
1038 dbus_bool_t
1039 bus_policy_test (const DBusString *test_data_dir)
1040 {
1041   /* This doesn't do anything for now because I decided to do it in
1042    * dispatch.c instead by having some of the clients in dispatch.c
1043    * have particular policies applied to them.
1044    */
1045   
1046   return TRUE;
1047 }
1048
1049 #endif /* DBUS_BUILD_TESTS */