Add optional logging on allow rules
[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                                   dbus_int32_t    *toggles,
871                                   dbus_bool_t     *log)
872 {
873   DBusList *link;
874   dbus_bool_t allowed;
875   
876   /* policy->rules is in the order the rules appeared
877    * in the config file, i.e. last rule that applies wins
878    */
879
880   _dbus_verbose ("  (policy) checking send rules\n");
881   *toggles = 0;
882   
883   allowed = FALSE;
884   link = _dbus_list_get_first_link (&policy->rules);
885   while (link != NULL)
886     {
887       BusPolicyRule *rule = link->data;
888
889       link = _dbus_list_get_next_link (&policy->rules, link);
890       
891       /* Rule is skipped if it specifies a different
892        * message name from the message, or a different
893        * destination from the message
894        */
895       
896       if (rule->type != BUS_POLICY_RULE_SEND)
897         {
898           _dbus_verbose ("  (policy) skipping non-send rule\n");
899           continue;
900         }
901
902       if (rule->d.send.message_type != DBUS_MESSAGE_TYPE_INVALID)
903         {
904           if (dbus_message_get_type (message) != rule->d.send.message_type)
905             {
906               _dbus_verbose ("  (policy) skipping rule for different message type\n");
907               continue;
908             }
909         }
910
911       /* If it's a reply, the requested_reply flag kicks in */
912       if (dbus_message_get_reply_serial (message) != 0)
913         {
914           /* for allow, requested_reply=true means the rule applies
915            * only when reply was requested. requested_reply=false means
916            * always allow.
917            */
918           if (!requested_reply && rule->allow && rule->d.send.requested_reply && !rule->d.send.eavesdrop)
919             {
920               _dbus_verbose ("  (policy) skipping allow rule since it only applies to requested replies and does not allow eavesdropping\n");
921               continue;
922             }
923
924           /* for deny, requested_reply=false means the rule applies only
925            * when the reply was not requested. requested_reply=true means the
926            * rule always applies.
927            */
928           if (requested_reply && !rule->allow && !rule->d.send.requested_reply)
929             {
930               _dbus_verbose ("  (policy) skipping deny rule since it only applies to unrequested replies\n");
931               continue;
932             }
933         }
934       
935       if (rule->d.send.path != NULL)
936         {
937           if (dbus_message_get_path (message) != NULL &&
938               strcmp (dbus_message_get_path (message),
939                       rule->d.send.path) != 0)
940             {
941               _dbus_verbose ("  (policy) skipping rule for different path\n");
942               continue;
943             }
944         }
945       
946       if (rule->d.send.interface != NULL)
947         {
948           /* The interface is optional in messages. For allow rules, if the message
949            * has no interface we want to skip the rule (and thus not allow);
950            * for deny rules, if the message has no interface we want to use the
951            * rule (and thus deny).
952            */
953           dbus_bool_t no_interface;
954
955           no_interface = dbus_message_get_interface (message) == NULL;
956           
957           if ((no_interface && rule->allow) ||
958               (!no_interface && 
959                strcmp (dbus_message_get_interface (message),
960                        rule->d.send.interface) != 0))
961             {
962               _dbus_verbose ("  (policy) skipping rule for different interface\n");
963               continue;
964             }
965         }
966
967       if (rule->d.send.member != NULL)
968         {
969           if (dbus_message_get_member (message) != NULL &&
970               strcmp (dbus_message_get_member (message),
971                       rule->d.send.member) != 0)
972             {
973               _dbus_verbose ("  (policy) skipping rule for different member\n");
974               continue;
975             }
976         }
977
978       if (rule->d.send.error != NULL)
979         {
980           if (dbus_message_get_error_name (message) != NULL &&
981               strcmp (dbus_message_get_error_name (message),
982                       rule->d.send.error) != 0)
983             {
984               _dbus_verbose ("  (policy) skipping rule for different error name\n");
985               continue;
986             }
987         }
988       
989       if (rule->d.send.destination != NULL)
990         {
991           /* receiver can be NULL for messages that are sent to the
992            * message bus itself, we check the strings in that case as
993            * built-in services don't have a DBusConnection but messages
994            * to them have a destination service name.
995            */
996           if (receiver == NULL)
997             {
998               if (!dbus_message_has_destination (message,
999                                                  rule->d.send.destination))
1000                 {
1001                   _dbus_verbose ("  (policy) skipping rule because message dest is not %s\n",
1002                                  rule->d.send.destination);
1003                   continue;
1004                 }
1005             }
1006           else
1007             {
1008               DBusString str;
1009               BusService *service;
1010               
1011               _dbus_string_init_const (&str, rule->d.send.destination);
1012               
1013               service = bus_registry_lookup (registry, &str);
1014               if (service == NULL)
1015                 {
1016                   _dbus_verbose ("  (policy) skipping rule because dest %s doesn't exist\n",
1017                                  rule->d.send.destination);
1018                   continue;
1019                 }
1020
1021               if (!bus_service_has_owner (service, receiver))
1022                 {
1023                   _dbus_verbose ("  (policy) skipping rule because dest %s isn't owned by receiver\n",
1024                                  rule->d.send.destination);
1025                   continue;
1026                 }
1027             }
1028         }
1029
1030       /* Use this rule */
1031       allowed = rule->allow;
1032       *log = rule->d.send.log;
1033       (*toggles)++;
1034
1035       _dbus_verbose ("  (policy) used rule, allow now = %d\n",
1036                      allowed);
1037     }
1038
1039   return allowed;
1040 }
1041
1042 /* See docs on what the args mean on bus_context_check_security_policy()
1043  * comment
1044  */
1045 dbus_bool_t
1046 bus_client_policy_check_can_receive (BusClientPolicy *policy,
1047                                      BusRegistry     *registry,
1048                                      dbus_bool_t      requested_reply,
1049                                      DBusConnection  *sender,
1050                                      DBusConnection  *addressed_recipient,
1051                                      DBusConnection  *proposed_recipient,
1052                                      DBusMessage     *message,
1053                                      dbus_int32_t    *toggles)
1054 {
1055   DBusList *link;
1056   dbus_bool_t allowed;
1057   dbus_bool_t eavesdropping;
1058
1059   eavesdropping =
1060     addressed_recipient != proposed_recipient &&
1061     dbus_message_get_destination (message) != NULL;
1062   
1063   /* policy->rules is in the order the rules appeared
1064    * in the config file, i.e. last rule that applies wins
1065    */
1066
1067   _dbus_verbose ("  (policy) checking receive rules, eavesdropping = %d\n", eavesdropping);
1068   *toggles = 0;
1069   
1070   allowed = FALSE;
1071   link = _dbus_list_get_first_link (&policy->rules);
1072   while (link != NULL)
1073     {
1074       BusPolicyRule *rule = link->data;
1075
1076       link = _dbus_list_get_next_link (&policy->rules, link);      
1077       
1078       if (rule->type != BUS_POLICY_RULE_RECEIVE)
1079         {
1080           _dbus_verbose ("  (policy) skipping non-receive rule\n");
1081           continue;
1082         }
1083
1084       if (rule->d.receive.message_type != DBUS_MESSAGE_TYPE_INVALID)
1085         {
1086           if (dbus_message_get_type (message) != rule->d.receive.message_type)
1087             {
1088               _dbus_verbose ("  (policy) skipping rule for different message type\n");
1089               continue;
1090             }
1091         }
1092
1093       /* for allow, eavesdrop=false means the rule doesn't apply when
1094        * eavesdropping. eavesdrop=true means always allow.
1095        */
1096       if (eavesdropping && rule->allow && !rule->d.receive.eavesdrop)
1097         {
1098           _dbus_verbose ("  (policy) skipping allow rule since it doesn't apply to eavesdropping\n");
1099           continue;
1100         }
1101
1102       /* for deny, eavesdrop=true means the rule applies only when
1103        * eavesdropping; eavesdrop=false means always deny.
1104        */
1105       if (!eavesdropping && !rule->allow && rule->d.receive.eavesdrop)
1106         {
1107           _dbus_verbose ("  (policy) skipping deny rule since it only applies to eavesdropping\n");
1108           continue;
1109         }
1110
1111       /* If it's a reply, the requested_reply flag kicks in */
1112       if (dbus_message_get_reply_serial (message) != 0)
1113         {
1114           /* for allow, requested_reply=true means the rule applies
1115            * only when reply was requested. requested_reply=false means
1116            * always allow.
1117            */
1118           if (!requested_reply && rule->allow && rule->d.receive.requested_reply && !rule->d.receive.eavesdrop)
1119             {
1120               _dbus_verbose ("  (policy) skipping allow rule since it only applies to requested replies and does not allow eavesdropping\n");
1121               continue;
1122             }
1123
1124           /* for deny, requested_reply=false means the rule applies only
1125            * when the reply was not requested. requested_reply=true means the
1126            * rule always applies.
1127            */
1128           if (requested_reply && !rule->allow && !rule->d.receive.requested_reply)
1129             {
1130               _dbus_verbose ("  (policy) skipping deny rule since it only applies to unrequested replies\n");
1131               continue;
1132             }
1133         }
1134       
1135       if (rule->d.receive.path != NULL)
1136         {
1137           if (dbus_message_get_path (message) != NULL &&
1138               strcmp (dbus_message_get_path (message),
1139                       rule->d.receive.path) != 0)
1140             {
1141               _dbus_verbose ("  (policy) skipping rule for different path\n");
1142               continue;
1143             }
1144         }
1145       
1146       if (rule->d.receive.interface != NULL)
1147         {
1148           /* The interface is optional in messages. For allow rules, if the message
1149            * has no interface we want to skip the rule (and thus not allow);
1150            * for deny rules, if the message has no interface we want to use the
1151            * rule (and thus deny).
1152            */
1153           dbus_bool_t no_interface;
1154
1155           no_interface = dbus_message_get_interface (message) == NULL;
1156           
1157           if ((no_interface && rule->allow) ||
1158               (!no_interface &&
1159                strcmp (dbus_message_get_interface (message),
1160                        rule->d.receive.interface) != 0))
1161             {
1162               _dbus_verbose ("  (policy) skipping rule for different interface\n");
1163               continue;
1164             }
1165         }      
1166
1167       if (rule->d.receive.member != NULL)
1168         {
1169           if (dbus_message_get_member (message) != NULL &&
1170               strcmp (dbus_message_get_member (message),
1171                       rule->d.receive.member) != 0)
1172             {
1173               _dbus_verbose ("  (policy) skipping rule for different member\n");
1174               continue;
1175             }
1176         }
1177
1178       if (rule->d.receive.error != NULL)
1179         {
1180           if (dbus_message_get_error_name (message) != NULL &&
1181               strcmp (dbus_message_get_error_name (message),
1182                       rule->d.receive.error) != 0)
1183             {
1184               _dbus_verbose ("  (policy) skipping rule for different error name\n");
1185               continue;
1186             }
1187         }
1188       
1189       if (rule->d.receive.origin != NULL)
1190         {          
1191           /* sender can be NULL for messages that originate from the
1192            * message bus itself, we check the strings in that case as
1193            * built-in services don't have a DBusConnection but will
1194            * still set the sender on their messages.
1195            */
1196           if (sender == NULL)
1197             {
1198               if (!dbus_message_has_sender (message,
1199                                             rule->d.receive.origin))
1200                 {
1201                   _dbus_verbose ("  (policy) skipping rule because message sender is not %s\n",
1202                                  rule->d.receive.origin);
1203                   continue;
1204                 }
1205             }
1206           else
1207             {
1208               BusService *service;
1209               DBusString str;
1210
1211               _dbus_string_init_const (&str, rule->d.receive.origin);
1212               
1213               service = bus_registry_lookup (registry, &str);
1214               
1215               if (service == NULL)
1216                 {
1217                   _dbus_verbose ("  (policy) skipping rule because origin %s doesn't exist\n",
1218                                  rule->d.receive.origin);
1219                   continue;
1220                 }
1221
1222               if (!bus_service_has_owner (service, sender))
1223                 {
1224                   _dbus_verbose ("  (policy) skipping rule because origin %s isn't owned by sender\n",
1225                                  rule->d.receive.origin);
1226                   continue;
1227                 }
1228             }
1229         }
1230       
1231       /* Use this rule */
1232       allowed = rule->allow;
1233       (*toggles)++;
1234
1235       _dbus_verbose ("  (policy) used rule, allow now = %d\n",
1236                      allowed);
1237     }
1238
1239   return allowed;
1240 }
1241
1242 dbus_bool_t
1243 bus_client_policy_check_can_own (BusClientPolicy  *policy,
1244                                  DBusConnection   *connection,
1245                                  const DBusString *service_name)
1246 {
1247   DBusList *link;
1248   dbus_bool_t allowed;
1249   
1250   /* policy->rules is in the order the rules appeared
1251    * in the config file, i.e. last rule that applies wins
1252    */
1253
1254   allowed = FALSE;
1255   link = _dbus_list_get_first_link (&policy->rules);
1256   while (link != NULL)
1257     {
1258       BusPolicyRule *rule = link->data;
1259
1260       link = _dbus_list_get_next_link (&policy->rules, link);
1261       
1262       /* Rule is skipped if it specifies a different service name from
1263        * the desired one.
1264        */
1265       
1266       if (rule->type != BUS_POLICY_RULE_OWN)
1267         continue;
1268
1269       if (rule->d.own.service_name != NULL)
1270         {
1271           if (!_dbus_string_equal_c_str (service_name,
1272                                          rule->d.own.service_name))
1273             continue;
1274         }
1275
1276       /* Use this rule */
1277       allowed = rule->allow;
1278     }
1279
1280   return allowed;
1281 }
1282
1283 #ifdef DBUS_BUILD_TESTS
1284
1285 dbus_bool_t
1286 bus_policy_test (const DBusString *test_data_dir)
1287 {
1288   /* This doesn't do anything for now because I decided to do it in
1289    * dispatch.c instead by having some of the clients in dispatch.c
1290    * have particular policies applied to them.
1291    */
1292   
1293   return TRUE;
1294 }
1295
1296 #endif /* DBUS_BUILD_TESTS */