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