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