• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
32 BusPolicyRule*
bus_policy_rule_new(BusPolicyRuleType type,dbus_bool_t allow)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 *
bus_policy_rule_ref(BusPolicyRule * rule)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
bus_policy_rule_unref(BusPolicyRule * rule)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
free_rule_func(void * data,void * user_data)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
free_rule_list_func(void * data)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*
bus_policy_new(void)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 *
bus_policy_ref(BusPolicy * policy)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
bus_policy_unref(BusPolicy * policy)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
add_list_to_client(DBusList ** list,BusClientPolicy * client)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*
bus_policy_create_client_policy(BusPolicy * policy,DBusConnection * connection,DBusError * error)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_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       dbus_set_error (error, DBUS_ERROR_FAILED,
327                       "No user ID known for connection, cannot determine security policy\n");
328       goto failed;
329     }
330 
331   if (_dbus_hash_table_get_n_entries (policy->rules_by_uid) > 0)
332     {
333       DBusList **list;
334 
335       list = _dbus_hash_table_lookup_ulong (policy->rules_by_uid,
336                                             uid);
337 
338       if (list != NULL)
339         {
340           if (!add_list_to_client (list, client))
341             goto nomem;
342         }
343     }
344 
345   /* Add console rules */
346   at_console = _dbus_is_console_user (uid, error);
347 
348   if (at_console)
349     {
350       if (!add_list_to_client (&policy->at_console_true_rules, client))
351         goto nomem;
352     }
353   else if (dbus_error_is_set (error) == TRUE)
354     {
355       goto failed;
356     }
357   else if (!add_list_to_client (&policy->at_console_false_rules, client))
358     {
359       goto nomem;
360     }
361 
362   if (!add_list_to_client (&policy->mandatory_rules,
363                            client))
364     goto nomem;
365 
366   bus_client_policy_optimize (client);
367 
368   return client;
369 
370  nomem:
371   BUS_SET_OOM (error);
372  failed:
373   _DBUS_ASSERT_ERROR_IS_SET (error);
374   if (client)
375     bus_client_policy_unref (client);
376   return NULL;
377 }
378 
379 static dbus_bool_t
list_allows_user(dbus_bool_t def,DBusList ** list,unsigned long uid,const unsigned long * group_ids,int n_group_ids)380 list_allows_user (dbus_bool_t           def,
381                   DBusList            **list,
382                   unsigned long         uid,
383                   const unsigned long  *group_ids,
384                   int                   n_group_ids)
385 {
386   DBusList *link;
387   dbus_bool_t allowed;
388 
389   allowed = def;
390 
391   link = _dbus_list_get_first_link (list);
392   while (link != NULL)
393     {
394       BusPolicyRule *rule = link->data;
395       link = _dbus_list_get_next_link (list, link);
396 
397       if (rule->type == BUS_POLICY_RULE_USER)
398         {
399           _dbus_verbose ("List %p user rule uid="DBUS_UID_FORMAT"\n",
400                          list, rule->d.user.uid);
401 
402           if (rule->d.user.uid == DBUS_UID_UNSET)
403             ; /* '*' wildcard */
404           else if (rule->d.user.uid != uid)
405             continue;
406         }
407       else if (rule->type == BUS_POLICY_RULE_GROUP)
408         {
409           _dbus_verbose ("List %p group rule uid="DBUS_UID_FORMAT"\n",
410                          list, rule->d.user.uid);
411 
412           if (rule->d.group.gid == DBUS_GID_UNSET)
413             ;  /* '*' wildcard */
414           else
415             {
416               int i;
417 
418               i = 0;
419               while (i < n_group_ids)
420                 {
421                   if (rule->d.group.gid == group_ids[i])
422                     break;
423                   ++i;
424                 }
425 
426               if (i == n_group_ids)
427                 continue;
428             }
429         }
430       else
431         continue;
432 
433       allowed = rule->allow;
434     }
435 
436   return allowed;
437 }
438 
439 dbus_bool_t
bus_policy_allow_user(BusPolicy * policy,DBusUserDatabase * user_database,unsigned long uid)440 bus_policy_allow_user (BusPolicy        *policy,
441                        DBusUserDatabase *user_database,
442                        unsigned long     uid)
443 {
444   dbus_bool_t allowed;
445   unsigned long *group_ids;
446   int n_group_ids;
447 
448   /* On OOM or error we always reject the user */
449   if (!_dbus_user_database_get_groups (user_database,
450                                        uid, &group_ids, &n_group_ids, NULL))
451     {
452       _dbus_verbose ("Did not get any groups for UID %lu\n",
453                      uid);
454       return FALSE;
455     }
456 
457   /* Default to "user owning bus" or root can connect */
458   allowed = uid == _dbus_getuid ();
459 
460   allowed = list_allows_user (allowed,
461                               &policy->default_rules,
462                               uid,
463                               group_ids, n_group_ids);
464 
465   allowed = list_allows_user (allowed,
466                               &policy->mandatory_rules,
467                               uid,
468                               group_ids, n_group_ids);
469 
470   dbus_free (group_ids);
471 
472   _dbus_verbose ("UID %lu allowed = %d\n", uid, allowed);
473 
474   return allowed;
475 }
476 
477 dbus_bool_t
bus_policy_append_default_rule(BusPolicy * policy,BusPolicyRule * rule)478 bus_policy_append_default_rule (BusPolicy      *policy,
479                                 BusPolicyRule  *rule)
480 {
481   if (!_dbus_list_append (&policy->default_rules, rule))
482     return FALSE;
483 
484   bus_policy_rule_ref (rule);
485 
486   return TRUE;
487 }
488 
489 dbus_bool_t
bus_policy_append_mandatory_rule(BusPolicy * policy,BusPolicyRule * rule)490 bus_policy_append_mandatory_rule (BusPolicy      *policy,
491                                   BusPolicyRule  *rule)
492 {
493   if (!_dbus_list_append (&policy->mandatory_rules, rule))
494     return FALSE;
495 
496   bus_policy_rule_ref (rule);
497 
498   return TRUE;
499 }
500 
501 
502 
503 static DBusList**
get_list(DBusHashTable * hash,unsigned long key)504 get_list (DBusHashTable *hash,
505           unsigned long  key)
506 {
507   DBusList **list;
508 
509   list = _dbus_hash_table_lookup_ulong (hash, key);
510 
511   if (list == NULL)
512     {
513       list = dbus_new0 (DBusList*, 1);
514       if (list == NULL)
515         return NULL;
516 
517       if (!_dbus_hash_table_insert_ulong (hash, key, list))
518         {
519           dbus_free (list);
520           return NULL;
521         }
522     }
523 
524   return list;
525 }
526 
527 dbus_bool_t
bus_policy_append_user_rule(BusPolicy * policy,dbus_uid_t uid,BusPolicyRule * rule)528 bus_policy_append_user_rule (BusPolicy      *policy,
529                              dbus_uid_t      uid,
530                              BusPolicyRule  *rule)
531 {
532   DBusList **list;
533 
534   list = get_list (policy->rules_by_uid, uid);
535 
536   if (list == NULL)
537     return FALSE;
538 
539   if (!_dbus_list_append (list, rule))
540     return FALSE;
541 
542   bus_policy_rule_ref (rule);
543 
544   return TRUE;
545 }
546 
547 dbus_bool_t
bus_policy_append_group_rule(BusPolicy * policy,dbus_gid_t gid,BusPolicyRule * rule)548 bus_policy_append_group_rule (BusPolicy      *policy,
549                               dbus_gid_t      gid,
550                               BusPolicyRule  *rule)
551 {
552   DBusList **list;
553 
554   list = get_list (policy->rules_by_gid, gid);
555 
556   if (list == NULL)
557     return FALSE;
558 
559   if (!_dbus_list_append (list, rule))
560     return FALSE;
561 
562   bus_policy_rule_ref (rule);
563 
564   return TRUE;
565 }
566 
567 dbus_bool_t
bus_policy_append_console_rule(BusPolicy * policy,dbus_bool_t at_console,BusPolicyRule * rule)568 bus_policy_append_console_rule (BusPolicy      *policy,
569                                 dbus_bool_t     at_console,
570                                 BusPolicyRule  *rule)
571 {
572   if (at_console)
573     {
574       if (!_dbus_list_append (&policy->at_console_true_rules, rule))
575         return FALSE;
576     }
577     else
578     {
579       if (!_dbus_list_append (&policy->at_console_false_rules, rule))
580         return FALSE;
581     }
582 
583   bus_policy_rule_ref (rule);
584 
585   return TRUE;
586 
587 }
588 
589 static dbus_bool_t
append_copy_of_policy_list(DBusList ** list,DBusList ** to_append)590 append_copy_of_policy_list (DBusList **list,
591                             DBusList **to_append)
592 {
593   DBusList *link;
594   DBusList *tmp_list;
595 
596   tmp_list = NULL;
597 
598   /* Preallocate all our links */
599   link = _dbus_list_get_first_link (to_append);
600   while (link != NULL)
601     {
602       if (!_dbus_list_append (&tmp_list, link->data))
603         {
604           _dbus_list_clear (&tmp_list);
605           return FALSE;
606         }
607 
608       link = _dbus_list_get_next_link (to_append, link);
609     }
610 
611   /* Now append them */
612   while ((link = _dbus_list_pop_first_link (&tmp_list)))
613     {
614       bus_policy_rule_ref (link->data);
615       _dbus_list_append_link (list, link);
616     }
617 
618   return TRUE;
619 }
620 
621 static dbus_bool_t
merge_id_hash(DBusHashTable * dest,DBusHashTable * to_absorb)622 merge_id_hash (DBusHashTable *dest,
623                DBusHashTable *to_absorb)
624 {
625   DBusHashIter iter;
626 
627   _dbus_hash_iter_init (to_absorb, &iter);
628   while (_dbus_hash_iter_next (&iter))
629     {
630       unsigned long id = _dbus_hash_iter_get_ulong_key (&iter);
631       DBusList **list = _dbus_hash_iter_get_value (&iter);
632       DBusList **target = get_list (dest, id);
633 
634       if (target == NULL)
635         return FALSE;
636 
637       if (!append_copy_of_policy_list (target, list))
638         return FALSE;
639     }
640 
641   return TRUE;
642 }
643 
644 dbus_bool_t
bus_policy_merge(BusPolicy * policy,BusPolicy * to_absorb)645 bus_policy_merge (BusPolicy *policy,
646                   BusPolicy *to_absorb)
647 {
648   /* FIXME Not properly atomic, but as used for configuration files we
649    * don't rely on it quite so much.
650    */
651 
652   if (!append_copy_of_policy_list (&policy->default_rules,
653                                    &to_absorb->default_rules))
654     return FALSE;
655 
656   if (!append_copy_of_policy_list (&policy->mandatory_rules,
657                                    &to_absorb->mandatory_rules))
658     return FALSE;
659 
660   if (!append_copy_of_policy_list (&policy->at_console_true_rules,
661                                    &to_absorb->at_console_true_rules))
662     return FALSE;
663 
664   if (!append_copy_of_policy_list (&policy->at_console_false_rules,
665                                    &to_absorb->at_console_false_rules))
666     return FALSE;
667 
668   if (!merge_id_hash (policy->rules_by_uid,
669                       to_absorb->rules_by_uid))
670     return FALSE;
671 
672   if (!merge_id_hash (policy->rules_by_gid,
673                       to_absorb->rules_by_gid))
674     return FALSE;
675 
676   return TRUE;
677 }
678 
679 struct BusClientPolicy
680 {
681   int refcount;
682 
683   DBusList *rules;
684 };
685 
686 BusClientPolicy*
bus_client_policy_new(void)687 bus_client_policy_new (void)
688 {
689   BusClientPolicy *policy;
690 
691   policy = dbus_new0 (BusClientPolicy, 1);
692   if (policy == NULL)
693     return NULL;
694 
695   policy->refcount = 1;
696 
697   return policy;
698 }
699 
700 BusClientPolicy *
bus_client_policy_ref(BusClientPolicy * policy)701 bus_client_policy_ref (BusClientPolicy *policy)
702 {
703   _dbus_assert (policy->refcount > 0);
704 
705   policy->refcount += 1;
706 
707   return policy;
708 }
709 
710 static void
rule_unref_foreach(void * data,void * user_data)711 rule_unref_foreach (void *data,
712                     void *user_data)
713 {
714   BusPolicyRule *rule = data;
715 
716   bus_policy_rule_unref (rule);
717 }
718 
719 void
bus_client_policy_unref(BusClientPolicy * policy)720 bus_client_policy_unref (BusClientPolicy *policy)
721 {
722   _dbus_assert (policy->refcount > 0);
723 
724   policy->refcount -= 1;
725 
726   if (policy->refcount == 0)
727     {
728       _dbus_list_foreach (&policy->rules,
729                           rule_unref_foreach,
730                           NULL);
731 
732       _dbus_list_clear (&policy->rules);
733 
734       dbus_free (policy);
735     }
736 }
737 
738 static void
remove_rules_by_type_up_to(BusClientPolicy * policy,BusPolicyRuleType type,DBusList * up_to)739 remove_rules_by_type_up_to (BusClientPolicy   *policy,
740                             BusPolicyRuleType  type,
741                             DBusList          *up_to)
742 {
743   DBusList *link;
744 
745   link = _dbus_list_get_first_link (&policy->rules);
746   while (link != up_to)
747     {
748       BusPolicyRule *rule = link->data;
749       DBusList *next = _dbus_list_get_next_link (&policy->rules, link);
750 
751       if (rule->type == type)
752         {
753           _dbus_list_remove_link (&policy->rules, link);
754           bus_policy_rule_unref (rule);
755         }
756 
757       link = next;
758     }
759 }
760 
761 void
bus_client_policy_optimize(BusClientPolicy * policy)762 bus_client_policy_optimize (BusClientPolicy *policy)
763 {
764   DBusList *link;
765 
766   /* The idea here is that if we have:
767    *
768    * <allow send_interface="foo.bar"/>
769    * <deny send_interface="*"/>
770    *
771    * (for example) the deny will always override the allow.  So we
772    * delete the allow. Ditto for deny followed by allow, etc. This is
773    * a dumb thing to put in a config file, but the <include> feature
774    * of files allows for an "inheritance and override" pattern where
775    * it could make sense. If an included file wants to "start over"
776    * with a blanket deny, no point keeping the rules from the parent
777    * file.
778    */
779 
780   _dbus_verbose ("Optimizing policy with %d rules\n",
781                  _dbus_list_get_length (&policy->rules));
782 
783   link = _dbus_list_get_first_link (&policy->rules);
784   while (link != NULL)
785     {
786       BusPolicyRule *rule;
787       DBusList *next;
788       dbus_bool_t remove_preceding;
789 
790       next = _dbus_list_get_next_link (&policy->rules, link);
791       rule = link->data;
792 
793       remove_preceding = FALSE;
794 
795       _dbus_assert (rule != NULL);
796 
797       switch (rule->type)
798         {
799         case BUS_POLICY_RULE_SEND:
800           remove_preceding =
801             rule->d.send.message_type == DBUS_MESSAGE_TYPE_INVALID &&
802             rule->d.send.path == NULL &&
803             rule->d.send.interface == NULL &&
804             rule->d.send.member == NULL &&
805             rule->d.send.error == NULL &&
806             rule->d.send.destination == NULL;
807           break;
808         case BUS_POLICY_RULE_RECEIVE:
809           remove_preceding =
810             rule->d.receive.message_type == DBUS_MESSAGE_TYPE_INVALID &&
811             rule->d.receive.path == NULL &&
812             rule->d.receive.interface == NULL &&
813             rule->d.receive.member == NULL &&
814             rule->d.receive.error == NULL &&
815             rule->d.receive.origin == NULL;
816           break;
817         case BUS_POLICY_RULE_OWN:
818           remove_preceding =
819             rule->d.own.service_name == NULL;
820           break;
821         case BUS_POLICY_RULE_USER:
822         case BUS_POLICY_RULE_GROUP:
823           _dbus_assert_not_reached ("invalid rule");
824           break;
825         }
826 
827       if (remove_preceding)
828         remove_rules_by_type_up_to (policy, rule->type,
829                                     link);
830 
831       link = next;
832     }
833 
834   _dbus_verbose ("After optimization, policy has %d rules\n",
835                  _dbus_list_get_length (&policy->rules));
836 }
837 
838 dbus_bool_t
bus_client_policy_append_rule(BusClientPolicy * policy,BusPolicyRule * rule)839 bus_client_policy_append_rule (BusClientPolicy *policy,
840                                BusPolicyRule   *rule)
841 {
842   _dbus_verbose ("Appending rule %p with type %d to policy %p\n",
843                  rule, rule->type, policy);
844 
845   if (!_dbus_list_append (&policy->rules, rule))
846     return FALSE;
847 
848   bus_policy_rule_ref (rule);
849 
850   return TRUE;
851 }
852 
853 dbus_bool_t
bus_client_policy_check_can_send(BusClientPolicy * policy,BusRegistry * registry,dbus_bool_t requested_reply,DBusConnection * receiver,DBusMessage * message)854 bus_client_policy_check_can_send (BusClientPolicy *policy,
855                                   BusRegistry     *registry,
856                                   dbus_bool_t      requested_reply,
857                                   DBusConnection  *receiver,
858                                   DBusMessage     *message)
859 {
860   DBusList *link;
861   dbus_bool_t allowed;
862 
863   /* policy->rules is in the order the rules appeared
864    * in the config file, i.e. last rule that applies wins
865    */
866 
867   _dbus_verbose ("  (policy) checking send rules\n");
868 
869   allowed = FALSE;
870   link = _dbus_list_get_first_link (&policy->rules);
871   while (link != NULL)
872     {
873       BusPolicyRule *rule = link->data;
874 
875       link = _dbus_list_get_next_link (&policy->rules, link);
876 
877       /* Rule is skipped if it specifies a different
878        * message name from the message, or a different
879        * destination from the message
880        */
881 
882       if (rule->type != BUS_POLICY_RULE_SEND)
883         {
884           _dbus_verbose ("  (policy) skipping non-send rule\n");
885           continue;
886         }
887 
888       if (rule->d.send.message_type != DBUS_MESSAGE_TYPE_INVALID)
889         {
890           if (dbus_message_get_type (message) != rule->d.send.message_type)
891             {
892               _dbus_verbose ("  (policy) skipping rule for different message type\n");
893               continue;
894             }
895         }
896 
897       /* If it's a reply, the requested_reply flag kicks in */
898       if (dbus_message_get_reply_serial (message) != 0)
899         {
900           /* for allow, requested_reply=true means the rule applies
901            * only when reply was requested. requested_reply=false means
902            * always allow.
903            */
904           if (!requested_reply && rule->allow && rule->d.send.requested_reply)
905             {
906               _dbus_verbose ("  (policy) skipping allow rule since it only applies to requested replies\n");
907               continue;
908             }
909 
910           /* for deny, requested_reply=false means the rule applies only
911            * when the reply was not requested. requested_reply=true means the
912            * rule always applies.
913            */
914           if (requested_reply && !rule->allow && !rule->d.send.requested_reply)
915             {
916               _dbus_verbose ("  (policy) skipping deny rule since it only applies to unrequested replies\n");
917               continue;
918             }
919         }
920 
921       if (rule->d.send.path != NULL)
922         {
923           if (dbus_message_get_path (message) != NULL &&
924               strcmp (dbus_message_get_path (message),
925                       rule->d.send.path) != 0)
926             {
927               _dbus_verbose ("  (policy) skipping rule for different path\n");
928               continue;
929             }
930         }
931 
932       if (rule->d.send.interface != NULL)
933         {
934           if (dbus_message_get_interface (message) != NULL &&
935               strcmp (dbus_message_get_interface (message),
936                       rule->d.send.interface) != 0)
937             {
938               _dbus_verbose ("  (policy) skipping rule for different interface\n");
939               continue;
940             }
941         }
942 
943       if (rule->d.send.member != NULL)
944         {
945           if (dbus_message_get_member (message) != NULL &&
946               strcmp (dbus_message_get_member (message),
947                       rule->d.send.member) != 0)
948             {
949               _dbus_verbose ("  (policy) skipping rule for different member\n");
950               continue;
951             }
952         }
953 
954       if (rule->d.send.error != NULL)
955         {
956           if (dbus_message_get_error_name (message) != NULL &&
957               strcmp (dbus_message_get_error_name (message),
958                       rule->d.send.error) != 0)
959             {
960               _dbus_verbose ("  (policy) skipping rule for different error name\n");
961               continue;
962             }
963         }
964 
965       if (rule->d.send.destination != NULL)
966         {
967           /* receiver can be NULL for messages that are sent to the
968            * message bus itself, we check the strings in that case as
969            * built-in services don't have a DBusConnection but messages
970            * to them have a destination service name.
971            */
972           if (receiver == NULL)
973             {
974               if (!dbus_message_has_destination (message,
975                                                  rule->d.send.destination))
976                 {
977                   _dbus_verbose ("  (policy) skipping rule because message dest is not %s\n",
978                                  rule->d.send.destination);
979                   continue;
980                 }
981             }
982           else
983             {
984               DBusString str;
985               BusService *service;
986 
987               _dbus_string_init_const (&str, rule->d.send.destination);
988 
989               service = bus_registry_lookup (registry, &str);
990               if (service == NULL)
991                 {
992                   _dbus_verbose ("  (policy) skipping rule because dest %s doesn't exist\n",
993                                  rule->d.send.destination);
994                   continue;
995                 }
996 
997               if (!bus_service_has_owner (service, receiver))
998                 {
999                   _dbus_verbose ("  (policy) skipping rule because dest %s isn't owned by receiver\n",
1000                                  rule->d.send.destination);
1001                   continue;
1002                 }
1003             }
1004         }
1005 
1006       /* Use this rule */
1007       allowed = rule->allow;
1008 
1009       _dbus_verbose ("  (policy) used rule, allow now = %d\n",
1010                      allowed);
1011     }
1012 
1013   return allowed;
1014 }
1015 
1016 /* See docs on what the args mean on bus_context_check_security_policy()
1017  * comment
1018  */
1019 dbus_bool_t
bus_client_policy_check_can_receive(BusClientPolicy * policy,BusRegistry * registry,dbus_bool_t requested_reply,DBusConnection * sender,DBusConnection * addressed_recipient,DBusConnection * proposed_recipient,DBusMessage * message)1020 bus_client_policy_check_can_receive (BusClientPolicy *policy,
1021                                      BusRegistry     *registry,
1022                                      dbus_bool_t      requested_reply,
1023                                      DBusConnection  *sender,
1024                                      DBusConnection  *addressed_recipient,
1025                                      DBusConnection  *proposed_recipient,
1026                                      DBusMessage     *message)
1027 {
1028   DBusList *link;
1029   dbus_bool_t allowed;
1030   dbus_bool_t eavesdropping;
1031 
1032   eavesdropping =
1033     addressed_recipient != proposed_recipient &&
1034     dbus_message_get_destination (message) != NULL;
1035 
1036   /* policy->rules is in the order the rules appeared
1037    * in the config file, i.e. last rule that applies wins
1038    */
1039 
1040   _dbus_verbose ("  (policy) checking receive rules, eavesdropping = %d\n", eavesdropping);
1041 
1042   allowed = FALSE;
1043   link = _dbus_list_get_first_link (&policy->rules);
1044   while (link != NULL)
1045     {
1046       BusPolicyRule *rule = link->data;
1047 
1048       link = _dbus_list_get_next_link (&policy->rules, link);
1049 
1050       if (rule->type != BUS_POLICY_RULE_RECEIVE)
1051         {
1052           _dbus_verbose ("  (policy) skipping non-receive rule\n");
1053           continue;
1054         }
1055 
1056       if (rule->d.receive.message_type != DBUS_MESSAGE_TYPE_INVALID)
1057         {
1058           if (dbus_message_get_type (message) != rule->d.receive.message_type)
1059             {
1060               _dbus_verbose ("  (policy) skipping rule for different message type\n");
1061               continue;
1062             }
1063         }
1064 
1065       /* for allow, eavesdrop=false means the rule doesn't apply when
1066        * eavesdropping. eavesdrop=true means always allow.
1067        */
1068       if (eavesdropping && rule->allow && !rule->d.receive.eavesdrop)
1069         {
1070           _dbus_verbose ("  (policy) skipping allow rule since it doesn't apply to eavesdropping\n");
1071           continue;
1072         }
1073 
1074       /* for deny, eavesdrop=true means the rule applies only when
1075        * eavesdropping; eavesdrop=false means always deny.
1076        */
1077       if (!eavesdropping && !rule->allow && rule->d.receive.eavesdrop)
1078         {
1079           _dbus_verbose ("  (policy) skipping deny rule since it only applies to eavesdropping\n");
1080           continue;
1081         }
1082 
1083       /* If it's a reply, the requested_reply flag kicks in */
1084       if (dbus_message_get_reply_serial (message) != 0)
1085         {
1086           /* for allow, requested_reply=true means the rule applies
1087            * only when reply was requested. requested_reply=false means
1088            * always allow.
1089            */
1090           if (!requested_reply && rule->allow && rule->d.receive.requested_reply)
1091             {
1092               _dbus_verbose ("  (policy) skipping allow rule since it only applies to requested replies\n");
1093               continue;
1094             }
1095 
1096           /* for deny, requested_reply=false means the rule applies only
1097            * when the reply was not requested. requested_reply=true means the
1098            * rule always applies.
1099            */
1100           if (requested_reply && !rule->allow && !rule->d.receive.requested_reply)
1101             {
1102               _dbus_verbose ("  (policy) skipping deny rule since it only applies to unrequested replies\n");
1103               continue;
1104             }
1105         }
1106 
1107       if (rule->d.receive.path != NULL)
1108         {
1109           if (dbus_message_get_path (message) != NULL &&
1110               strcmp (dbus_message_get_path (message),
1111                       rule->d.receive.path) != 0)
1112             {
1113               _dbus_verbose ("  (policy) skipping rule for different path\n");
1114               continue;
1115             }
1116         }
1117 
1118       if (rule->d.receive.interface != NULL)
1119         {
1120           if (dbus_message_get_interface (message) != NULL &&
1121               strcmp (dbus_message_get_interface (message),
1122                       rule->d.receive.interface) != 0)
1123             {
1124               _dbus_verbose ("  (policy) skipping rule for different interface\n");
1125               continue;
1126             }
1127         }
1128 
1129       if (rule->d.receive.member != NULL)
1130         {
1131           if (dbus_message_get_member (message) != NULL &&
1132               strcmp (dbus_message_get_member (message),
1133                       rule->d.receive.member) != 0)
1134             {
1135               _dbus_verbose ("  (policy) skipping rule for different member\n");
1136               continue;
1137             }
1138         }
1139 
1140       if (rule->d.receive.error != NULL)
1141         {
1142           if (dbus_message_get_error_name (message) != NULL &&
1143               strcmp (dbus_message_get_error_name (message),
1144                       rule->d.receive.error) != 0)
1145             {
1146               _dbus_verbose ("  (policy) skipping rule for different error name\n");
1147               continue;
1148             }
1149         }
1150 
1151       if (rule->d.receive.origin != NULL)
1152         {
1153           /* sender can be NULL for messages that originate from the
1154            * message bus itself, we check the strings in that case as
1155            * built-in services don't have a DBusConnection but will
1156            * still set the sender on their messages.
1157            */
1158           if (sender == NULL)
1159             {
1160               if (!dbus_message_has_sender (message,
1161                                             rule->d.receive.origin))
1162                 {
1163                   _dbus_verbose ("  (policy) skipping rule because message sender is not %s\n",
1164                                  rule->d.receive.origin);
1165                   continue;
1166                 }
1167             }
1168           else
1169             {
1170               BusService *service;
1171               DBusString str;
1172 
1173               _dbus_string_init_const (&str, rule->d.receive.origin);
1174 
1175               service = bus_registry_lookup (registry, &str);
1176 
1177               if (service == NULL)
1178                 {
1179                   _dbus_verbose ("  (policy) skipping rule because origin %s doesn't exist\n",
1180                                  rule->d.receive.origin);
1181                   continue;
1182                 }
1183 
1184               if (!bus_service_has_owner (service, sender))
1185                 {
1186                   _dbus_verbose ("  (policy) skipping rule because origin %s isn't owned by sender\n",
1187                                  rule->d.receive.origin);
1188                   continue;
1189                 }
1190             }
1191         }
1192 
1193       /* Use this rule */
1194       allowed = rule->allow;
1195 
1196       _dbus_verbose ("  (policy) used rule, allow now = %d\n",
1197                      allowed);
1198     }
1199 
1200   return allowed;
1201 }
1202 
1203 dbus_bool_t
bus_client_policy_check_can_own(BusClientPolicy * policy,DBusConnection * connection,const DBusString * service_name)1204 bus_client_policy_check_can_own (BusClientPolicy  *policy,
1205                                  DBusConnection   *connection,
1206                                  const DBusString *service_name)
1207 {
1208   DBusList *link;
1209   dbus_bool_t allowed;
1210 
1211   /* policy->rules is in the order the rules appeared
1212    * in the config file, i.e. last rule that applies wins
1213    */
1214 
1215   allowed = FALSE;
1216   link = _dbus_list_get_first_link (&policy->rules);
1217   while (link != NULL)
1218     {
1219       BusPolicyRule *rule = link->data;
1220 
1221       link = _dbus_list_get_next_link (&policy->rules, link);
1222 
1223       /* Rule is skipped if it specifies a different service name from
1224        * the desired one.
1225        */
1226 
1227       if (rule->type != BUS_POLICY_RULE_OWN)
1228         continue;
1229 
1230       if (rule->d.own.service_name != NULL)
1231         {
1232           if (!_dbus_string_equal_c_str (service_name,
1233                                          rule->d.own.service_name))
1234             continue;
1235         }
1236 
1237       /* Use this rule */
1238       allowed = rule->allow;
1239     }
1240 
1241   return allowed;
1242 }
1243 
1244 #ifdef DBUS_BUILD_TESTS
1245 
1246 dbus_bool_t
bus_policy_test(const DBusString * test_data_dir)1247 bus_policy_test (const DBusString *test_data_dir)
1248 {
1249   /* This doesn't do anything for now because I decided to do it in
1250    * dispatch.c instead by having some of the clients in dispatch.c
1251    * have particular policies applied to them.
1252    */
1253 
1254   return TRUE;
1255 }
1256 
1257 #endif /* DBUS_BUILD_TESTS */
1258