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