meta-tizen: meta: fix refactor to a better layout
[scm/bb/tizen-distro.git] / meta-tizen / meta-tizen-adaptation / meta / recipes-core / dbus / files / 0013-Enforce-smack-policy-from-conf-file.patch
1 From: Brian McGillion <brian.mcgillion@intel.com>
2 Date: Mon, 6 Feb 2012 18:48:30 +0200
3 Subject: Enforce smack policy from conf file
4
5 ---
6  bus/config-parser.c |  38 ++++++++++----
7  bus/policy.c        | 141 +++++++++++++++++++++++++++++++++++++++++++++++++---
8  bus/policy.h        |   3 ++
9  bus/smack.c         | 111 +++++++++++++++++++++++++++++++++++++++++
10  bus/smack.h         |   4 ++
11  5 files changed, 278 insertions(+), 19 deletions(-)
12
13 diff --git a/bus/config-parser.c b/bus/config-parser.c
14 index 07e8fbb..d7ba549 100644
15 --- a/bus/config-parser.c
16 +++ b/bus/config-parser.c
17 @@ -43,6 +43,7 @@ typedef enum
18    POLICY_MANDATORY,
19    POLICY_USER,
20    POLICY_GROUP,
21 +  POLICY_SMACK,
22    POLICY_CONSOLE
23  } PolicyType;
24  
25 @@ -64,7 +65,11 @@ typedef struct
26      struct
27      {
28        PolicyType type;
29 -      unsigned long gid_uid_or_at_console;      
30 +      union
31 +      {
32 +        unsigned long gid_uid_or_at_console;
33 +        char *smack_label;
34 +      };
35      } policy;
36  
37      struct
38 @@ -150,6 +155,8 @@ element_free (Element *e)
39  {
40    if (e->type == ELEMENT_LIMIT)
41      dbus_free (e->d.limit.name);
42 +  else if (e->type == ELEMENT_POLICY && e->d.policy.type == POLICY_SMACK)
43 +      dbus_free (e->d.policy.smack_label);
44    
45    dbus_free (e);
46  }
47 @@ -972,6 +979,7 @@ start_busconfig_child (BusConfigParser   *parser,
48        const char *user;
49        const char *group;
50        const char *at_console;
51 +      const char *smack;
52  
53        if ((e = push_element (parser, ELEMENT_POLICY)) == NULL)
54          {
55 @@ -988,20 +996,16 @@ start_busconfig_child (BusConfigParser   *parser,
56                                "context", &context,
57                                "user", &user,
58                                "group", &group,
59 +                              "smack", &smack,
60                                "at_console", &at_console,
61                                NULL))
62          return FALSE;
63  
64 -      if (((context && user) ||
65 -           (context && group) ||
66 -           (context && at_console)) ||
67 -           ((user && group) ||
68 -           (user && at_console)) ||
69 -           (group && at_console) ||
70 -          !(context || user || group || at_console))
71 +      if (((context != NULL) + (user != NULL) + (group != NULL) +
72 +          (smack != NULL) + (at_console != NULL)) != 1)
73          {
74            dbus_set_error (error, DBUS_ERROR_FAILED,
75 -                          "<policy> element must have exactly one of (context|user|group|at_console) attributes");
76 +                          "<policy> element must have exactly one of (context|user|group|smack|at_console) attributes");
77            return FALSE;
78          }
79  
80 @@ -1047,6 +1051,16 @@ start_busconfig_child (BusConfigParser   *parser,
81              _dbus_warn ("Unknown group \"%s\" in message bus configuration file\n",
82                          group);          
83          }
84 +      else if (smack != NULL)
85 +        {
86 +          e->d.policy.type = POLICY_SMACK;
87 +          e->d.policy.smack_label = _dbus_strdup (smack);
88 +          if (e->d.policy.smack_label == NULL)
89 +            {
90 +              BUS_SET_OOM (error);
91 +              return FALSE;
92 +            }
93 +        }
94        else if (at_console != NULL)
95          {
96             dbus_bool_t t;
97 @@ -1631,8 +1645,10 @@ append_rule_from_element (BusConfigParser   *parser,
98                                               rule))
99              goto nomem;
100            break;
101 -        
102 -
103 +        case POLICY_SMACK:
104 +          if (!bus_policy_append_smack_rule (parser->policy, pe->d.policy.smack_label, rule))
105 +            goto nomem;
106 +          break;
107          case POLICY_CONSOLE:
108            if (!bus_policy_append_console_rule (parser->policy, pe->d.policy.gid_uid_or_at_console,
109                                                 rule))
110 diff --git a/bus/policy.c b/bus/policy.c
111 index 379cea9..836354a 100644
112 --- a/bus/policy.c
113 +++ b/bus/policy.c
114 @@ -26,6 +26,7 @@
115  #include "services.h"
116  #include "test.h"
117  #include "utils.h"
118 +#include "smack.h"
119  #include <dbus/dbus-list.h>
120  #include <dbus/dbus-hash.h>
121  #include <dbus/dbus-internals.h>
122 @@ -126,12 +127,13 @@ struct BusPolicy
123  {
124    int refcount;
125  
126 -  DBusList *default_rules;         /**< Default policy rules */
127 -  DBusList *mandatory_rules;       /**< Mandatory policy rules */
128 -  DBusHashTable *rules_by_uid;     /**< per-UID policy rules */
129 -  DBusHashTable *rules_by_gid;     /**< per-GID policy rules */
130 -  DBusList *at_console_true_rules; /**< console user policy rules where at_console="true"*/
131 -  DBusList *at_console_false_rules; /**< console user policy rules where at_console="false"*/
132 +  DBusList *default_rules;             /**< Default policy rules */
133 +  DBusList *mandatory_rules;           /**< Mandatory policy rules */
134 +  DBusHashTable *rules_by_uid;         /**< per-UID policy rules */
135 +  DBusHashTable *rules_by_gid;         /**< per-GID policy rules */
136 +  DBusHashTable *rules_by_smack_label; /**< per-SMACK label policy rules */
137 +  DBusList *at_console_true_rules;     /**< console user policy rules where at_console="true"*/
138 +  DBusList *at_console_false_rules;    /**< console user policy rules where at_console="false"*/
139  };
140  
141  static void
142 @@ -181,6 +183,14 @@ bus_policy_new (void)
143    if (policy->rules_by_gid == NULL)
144      goto failed;
145  
146 +#ifdef DBUS_ENABLE_SMACK
147 +  policy->rules_by_smack_label = _dbus_hash_table_new (DBUS_HASH_STRING,
148 +                                                       (DBusFreeFunction) dbus_free,
149 +                                                       free_rule_list_func);
150 +  if (policy->rules_by_smack_label == NULL)
151 +    goto failed;
152 +#endif
153 +
154    return policy;
155    
156   failed:
157 @@ -230,7 +240,13 @@ bus_policy_unref (BusPolicy *policy)
158            _dbus_hash_table_unref (policy->rules_by_gid);
159            policy->rules_by_gid = NULL;
160          }
161 -      
162 +
163 +      if (policy->rules_by_smack_label)
164 +        {
165 +          _dbus_hash_table_unref (policy->rules_by_smack_label);
166 +          policy->rules_by_smack_label = NULL;
167 +        }
168 +
169        dbus_free (policy);
170      }
171  }
172 @@ -356,6 +372,24 @@ bus_policy_create_client_policy (BusPolicy      *policy,
173          }
174      }
175  
176 +  if (policy->rules_by_smack_label &&
177 +      _dbus_hash_table_get_n_entries (policy->rules_by_smack_label) > 0)
178 +    {
179 +      DBusList **list;
180 +      dbus_bool_t nomem_err = FALSE;
181 +
182 +      list = bus_smack_generate_allowed_list(connection, policy->rules_by_smack_label, &nomem_err);
183 +
184 +      if (list != NULL)
185 +        {
186 +          nomem_err = !add_list_to_client (list, client);
187 +          _dbus_list_clear (list);
188 +        }
189 +
190 +      if (nomem_err)
191 +        goto nomem;
192 +    }
193 +
194    if (!add_list_to_client (&policy->mandatory_rules,
195                             client))
196      goto nomem;
197 @@ -576,6 +610,66 @@ bus_policy_append_group_rule (BusPolicy      *policy,
198    return TRUE;
199  }
200  
201 +#ifdef DBUS_ENABLE_SMACK
202 +static DBusList **
203 +get_list_string (DBusHashTable *table,
204 +                 const char *key)
205 +{
206 +  DBusList **list;
207 +
208 +  if (key == NULL)
209 +      return NULL;
210 +
211 +  list = _dbus_hash_table_lookup_string (table, key);
212 +
213 +  if (list == NULL)
214 +    {
215 +      char *new_key;
216 +
217 +      list = dbus_new0 (DBusList*, 1);
218 +      if (list == NULL)
219 +        return NULL;
220 +
221 +      new_key = _dbus_strdup (key);
222 +      if (new_key == NULL)
223 +        {
224 +          dbus_free (list);
225 +          return NULL;
226 +        }
227 +
228 +      if (!_dbus_hash_table_insert_string (table, new_key, list))
229 +        {
230 +          dbus_free (list);
231 +          dbus_free (new_key);
232 +          return NULL;
233 +        }
234 +    }
235 +
236 +  return list;
237 +}
238 +#endif
239 +
240 +dbus_bool_t
241 +bus_policy_append_smack_rule (BusPolicy      *policy,
242 +                              const char     *label,
243 +                              BusPolicyRule  *rule)
244 +{
245 +#ifdef DBUS_ENABLE_SMACK
246 +  DBusList **list;
247 +
248 +  list = get_list_string (policy->rules_by_smack_label, label);
249 +  if (list == NULL)
250 +    return FALSE;
251 +
252 +  if (!_dbus_list_append (list, rule))
253 +    return FALSE;
254 +
255 +  bus_policy_rule_ref (rule);
256 +#endif
257 +
258 +  return TRUE;
259 +}
260 +
261  dbus_bool_t
262  bus_policy_append_console_rule (BusPolicy      *policy,
263                                  dbus_bool_t     at_console,
264 @@ -653,6 +747,31 @@ merge_id_hash (DBusHashTable *dest,
265    return TRUE;
266  }
267  
268 +#ifdef DBUS_ENABLE_SMACK
269 +static dbus_bool_t
270 +merge_string_hash (DBusHashTable *dest,
271 +                   DBusHashTable *to_absorb)
272 +{
273 +  DBusHashIter iter;
274 +
275 +  _dbus_hash_iter_init (to_absorb, &iter);
276 +  while (_dbus_hash_iter_next (&iter))
277 +    {
278 +      const char *absorb_label = _dbus_hash_iter_get_string_key(&iter);
279 +      DBusList **list = _dbus_hash_iter_get_value (&iter);
280 +      DBusList **target = get_list_string (dest, absorb_label);
281 +
282 +      if (target == NULL)
283 +        return FALSE;
284 +
285 +      if (!append_copy_of_policy_list (target, list))
286 +        return FALSE;
287 +    }
288 +
289 +  return TRUE;
290 +}
291 +#endif
292 +
293  dbus_bool_t
294  bus_policy_merge (BusPolicy *policy,
295                    BusPolicy *to_absorb)
296 @@ -685,6 +804,12 @@ bus_policy_merge (BusPolicy *policy,
297                        to_absorb->rules_by_gid))
298      return FALSE;
299  
300 +#ifdef DBUS_ENABLE_SMACK
301 +  if (!merge_string_hash (policy->rules_by_smack_label,
302 +                          to_absorb->rules_by_smack_label))
303 +    return FALSE;
304 +#endif
305 +
306    return TRUE;
307  }
308  
309 @@ -873,7 +998,7 @@ bus_client_policy_check_can_send (BusClientPolicy *policy,
310  {
311    DBusList *link;
312    dbus_bool_t allowed;
313 -  
314 +
315    /* policy->rules is in the order the rules appeared
316     * in the config file, i.e. last rule that applies wins
317     */
318 diff --git a/bus/policy.h b/bus/policy.h
319 index 3ff6f48..20d0a39 100644
320 --- a/bus/policy.h
321 +++ b/bus/policy.h
322 @@ -130,6 +130,9 @@ dbus_bool_t      bus_policy_append_user_rule      (BusPolicy        *policy,
323  dbus_bool_t      bus_policy_append_group_rule     (BusPolicy        *policy,
324                                                     dbus_gid_t        gid,
325                                                     BusPolicyRule    *rule);
326 +dbus_bool_t      bus_policy_append_smack_rule     (BusPolicy        *policy,
327 +                                                   const char       *label,
328 +                                                   BusPolicyRule    *rule);
329  dbus_bool_t      bus_policy_append_console_rule   (BusPolicy        *policy,
330                                                     dbus_bool_t        at_console,
331                                                     BusPolicyRule    *rule);
332 diff --git a/bus/smack.c b/bus/smack.c
333 index b8542c2..d4546a3 100644
334 --- a/bus/smack.c
335 +++ b/bus/smack.c
336 @@ -29,11 +29,17 @@
337  #include "connection.h"
338  #include "services.h"
339  #include "utils.h"
340 +#include "policy.h"
341  
342  #ifdef DBUS_ENABLE_SMACK
343  #include <sys/smack.h>
344  #endif
345  
346 +#define SMACK_WRITE "W"
347 +#define SMACK_READ "R"
348 +#define SMACK_READ_WRITE "RW"
349 +
350 +
351  #ifdef DBUS_ENABLE_SMACK
352  static char *
353  bus_smack_get_label (DBusConnection *connection)
354 @@ -130,3 +136,108 @@ err:
355    return FALSE;
356  #endif
357  }
358 +
359 +#ifdef DBUS_ENABLE_SMACK
360 +static dbus_bool_t
361 +bus_smack_has_access (const char *subject, const char *object,
362 +                      const char *access)
363 +{
364 +  return (smack_have_access (subject, object, access) == 1 ? TRUE : FALSE);
365 +}
366 +#endif
367 +
368 +
369 +/**
370 + * Calculate the list of rules that apply to a connection.
371 + *
372 + * @param connection The inbound conenction
373 + * @param rules_by_smack_label The table of object labels -> rules mapping
374 + * @param nomem_err (out) If a nomem situation is encountered this value is set to TRUE.
375 + * @returns the list of permitted rules if it exists and no errors were encountered otherwise NULL.
376 + */
377 +DBusList**
378 +bus_smack_generate_allowed_list (DBusConnection *connection,
379 +                                 DBusHashTable  *rules_by_smack_label,
380 +                                 dbus_bool_t *nomem_err)
381 +{
382 +#ifdef DBUS_ENABLE_SMACK
383 +  char *subject_label;
384 +  DBusHashIter iter;
385 +  dbus_bool_t is_allowed;
386 +  DBusList **allowed_list;
387 +
388 +  /* the label of the subject, is the label on the new connection,
389 +     either the service itself or one of its clients */
390 +  subject_label = bus_smack_get_label (connection);
391 +  if (subject_label == NULL)
392 +    return NULL;
393 +
394 +  allowed_list = dbus_new0 (DBusList*, 1);
395 +  if (allowed_list == NULL)
396 +    goto nomem;
397 +
398 +  /* Iterate over all the smack labels we have parsed from the .conf files */
399 +  _dbus_hash_iter_init (rules_by_smack_label, &iter);
400 +  while (_dbus_hash_iter_next (&iter))
401 +    {
402 +      DBusList *link;
403 +      const char *object_label = _dbus_hash_iter_get_string_key (&iter);
404 +      /* the list here is all the rules that are 'protected'
405 +         by the SMACK label named $object_label */
406 +      DBusList **list = _dbus_hash_iter_get_value (&iter);
407 +
408 +      link = _dbus_list_get_first_link (list);
409 +      while (link != NULL)
410 +        {
411 +          BusPolicyRule *rule = link->data;
412 +          link = _dbus_list_get_next_link (list, link);
413 +          is_allowed = FALSE;
414 +
415 +          switch (rule->type)
416 +            {
417 +            case BUS_POLICY_RULE_OWN:
418 +              is_allowed = bus_smack_has_access (subject_label,
419 +                                                 object_label,
420 +                                                 SMACK_READ_WRITE);
421 +              break;
422 +            case BUS_POLICY_RULE_SEND:
423 +              is_allowed = bus_smack_has_access (subject_label,
424 +                                                 object_label,
425 +                                                 SMACK_WRITE);
426 +              break;
427 +            case BUS_POLICY_RULE_RECEIVE:
428 +              is_allowed = bus_smack_has_access (subject_label,
429 +                                                 object_label,
430 +                                                 SMACK_READ);
431 +              break;
432 +            default:
433 +              continue;
434 +            }
435 +
436 +          if (is_allowed)
437 +            {
438 +              if (!_dbus_list_append (allowed_list, rule))
439 +                goto nomem;
440 +
441 +              bus_policy_rule_ref (rule);
442 +            }
443 +
444 +          _dbus_verbose ("permission request subject (%s) -> object (%s) : %s", subject_label, object_label, (is_allowed ? "GRANTED" : "REJECTED"));
445 +        }
446 +    }
447 +
448 +  dbus_free(subject_label);
449 +  return allowed_list;
450 +
451 +nomem:
452 +  if (allowed_list != NULL)
453 +    _dbus_list_clear (allowed_list);
454 +
455 +  dbus_free(subject_label);
456 +  *nomem_err = TRUE;
457 +  return NULL;
458 +
459 +#else
460 +  return NULL;
461 +#endif
462 +}
463 diff --git a/bus/smack.h b/bus/smack.h
464 index 04a4a2a..6b1dfad 100644
465 --- a/bus/smack.h
466 +++ b/bus/smack.h
467 @@ -27,10 +27,14 @@
468  #define SMACK_H
469  
470  #include "bus.h"
471 +#include <dbus/dbus-hash.h>
472  
473  dbus_bool_t bus_smack_handle_get_connection_context (DBusConnection *connection,
474                                                       BusTransaction *transaction,
475                                                       DBusMessage    *message,
476                                                       DBusError      *error);
477  
478 +DBusList **bus_smack_generate_allowed_list (DBusConnection *connection,
479 +                                            DBusHashTable *label_rules,
480 +                                            dbus_bool_t *error);
481  #endif // SMACK_H