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