Home | History | Annotate | Download | only in bus
      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*
     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_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 *
    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_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
    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
    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
    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
    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
    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**
    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
    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
    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
    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
    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
    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
    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*
    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 *
    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
    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
    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
    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
    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
    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
    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
   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
   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
   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