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