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