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