1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* policy.c Policies for what a connection can do
4 * Copyright (C) 2003 Red Hat, Inc.
6 * Licensed under the Academic Free License version 1.2
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.
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.
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
26 #include <dbus/dbus-list.h>
27 #include <dbus/dbus-internals.h>
30 bus_policy_rule_new (BusPolicyRuleType type,
35 rule = dbus_new0 (BusPolicyRule, 1);
47 bus_policy_rule_ref (BusPolicyRule *rule)
49 _dbus_assert (rule->refcount > 0);
55 bus_policy_rule_unref (BusPolicyRule *rule)
57 _dbus_assert (rule->refcount > 0);
61 if (rule->refcount == 0)
65 case BUS_POLICY_RULE_SEND:
66 dbus_free (rule->d.send.message_name);
67 dbus_free (rule->d.send.destination);
69 case BUS_POLICY_RULE_RECEIVE:
70 dbus_free (rule->d.receive.message_name);
71 dbus_free (rule->d.receive.origin);
73 case BUS_POLICY_RULE_OWN:
74 dbus_free (rule->d.own.service_name);
76 case BUS_POLICY_RULE_USER:
77 case BUS_POLICY_RULE_GROUP:
78 _dbus_assert_not_reached ("invalid rule");
98 policy = dbus_new0 (BusPolicy, 1);
102 policy->refcount = 1;
108 bus_policy_ref (BusPolicy *policy)
110 _dbus_assert (policy->refcount > 0);
112 policy->refcount += 1;
116 rule_unref_foreach (void *data,
119 BusPolicyRule *rule = data;
121 bus_policy_rule_unref (rule);
125 bus_policy_unref (BusPolicy *policy)
127 _dbus_assert (policy->refcount > 0);
129 policy->refcount -= 1;
131 if (policy->refcount == 0)
133 _dbus_list_foreach (&policy->rules,
137 _dbus_list_clear (&policy->rules);
144 remove_rules_by_type_up_to (BusPolicy *policy,
145 BusPolicyRuleType type,
150 link = _dbus_list_get_first (&policy->rules);
151 while (link != up_to)
153 BusPolicyRule *rule = link->data;
154 DBusList *next = _dbus_list_get_next_link (&policy->rules, link);
156 bus_policy_rule_unref (rule);
157 _dbus_list_remove_link (&policy->rules, link);
164 bus_policy_optimize (BusPolicy *policy)
168 /* The idea here is that if we have:
170 * <allow send="foo"/>
173 * (for example) the deny will always override the allow. So we
174 * delete the allow. Ditto for deny followed by allow, etc. This is
175 * a dumb thing to put in a config file, but the <include> feature
176 * of files allows for an "inheritance and override" pattern where
177 * it could make sense. If an included file wants to "start over"
178 * with a blanket deny, no point keeping the rules from the parent
182 _dbus_verbose ("Optimizing policy with %d rules\n",
183 _dbus_list_get_length (&policy->rules));
185 link = _dbus_list_get_first (&policy->rules);
188 BusPolicyRule *rule = link->data;
189 DBusList *next = _dbus_list_get_next_link (&policy->rules, link);
190 dbus_bool_t remove_preceding;
192 remove_preceding = FALSE;
196 case BUS_POLICY_RULE_SEND:
198 rule->d.send.message_name == NULL &&
199 rule->d.send.destination == NULL;
201 case BUS_POLICY_RULE_RECEIVE:
203 rule->d.receive.message_name == NULL &&
204 rule->d.receive.origin == NULL;
206 case BUS_POLICY_RULE_OWN:
208 rule->d.own.service_name == NULL;
210 case BUS_POLICY_RULE_USER:
211 case BUS_POLICY_RULE_GROUP:
212 _dbus_assert_not_reached ("invalid rule");
216 if (remove_preceding)
217 remove_rules_by_type_up_to (policy, rule->type,
223 _dbus_verbose ("After optimization, policy has %d rules\n",
224 _dbus_list_get_length (&policy->rules));
228 bus_policy_append_rule (BusPolicy *policy,
231 if (!_dbus_list_append (&policy->rules, rule))
234 bus_policy_rule_ref (rule);
240 bus_policy_check_can_send (BusPolicy *policy,
241 BusRegistry *registry,
242 DBusConnection *receiver,
243 DBusMessage *message)
248 /* policy->rules is in the order the rules appeared
249 * in the config file, i.e. last rule that applies wins
253 link = _dbus_list_get_first (&policy->rules);
256 BusPolicyRule *rule = link->data;
258 link = _dbus_list_get_next_link (&policy->rules, link);
260 /* Rule is skipped if it specifies a different
261 * message name from the message, or a different
262 * destination from the message
265 if (rule->type != BUS_POLICY_RULE_SEND)
268 if (rule->d.send.message_name != NULL)
270 if (!dbus_message_name_is (message,
271 rule->d.send.message_name))
275 if (rule->d.send.destination != NULL)
277 /* receiver can be NULL for messages that are sent to the
278 * message bus itself, we check the strings in that case as
279 * built-in services don't have a DBusConnection but messages
280 * to them have a destination service name.
282 if (receiver == NULL)
284 if (!dbus_message_sender_is (message,
285 rule->d.send.destination))
293 _dbus_string_init_const (&str, rule->d.send.destination);
295 service = bus_registry_lookup (registry, &str);
299 if (!bus_service_has_owner (service, receiver))
305 allowed = rule->allow;
312 bus_policy_check_can_receive (BusPolicy *policy,
313 BusRegistry *registry,
314 DBusConnection *sender,
315 DBusMessage *message)
320 /* policy->rules is in the order the rules appeared
321 * in the config file, i.e. last rule that applies wins
325 link = _dbus_list_get_first (&policy->rules);
328 BusPolicyRule *rule = link->data;
330 link = _dbus_list_get_next_link (&policy->rules, link);
332 /* Rule is skipped if it specifies a different
333 * message name from the message, or a different
334 * origin from the message
337 if (rule->type != BUS_POLICY_RULE_RECEIVE)
340 if (rule->d.receive.message_name != NULL)
342 if (!dbus_message_name_is (message,
343 rule->d.receive.message_name))
347 if (rule->d.receive.origin != NULL)
349 /* sender can be NULL for messages that originate from the
350 * message bus itself, we check the strings in that case as
351 * built-in services don't have a DBusConnection but will
352 * still set the sender on their messages.
356 if (!dbus_message_sender_is (message,
357 rule->d.receive.origin))
365 _dbus_string_init_const (&str, rule->d.receive.origin);
367 service = bus_registry_lookup (registry, &str);
372 if (!bus_service_has_owner (service, sender))
378 allowed = rule->allow;
385 bus_policy_check_can_own (BusPolicy *policy,
386 DBusConnection *connection,
387 const DBusString *service_name)
392 /* policy->rules is in the order the rules appeared
393 * in the config file, i.e. last rule that applies wins
397 link = _dbus_list_get_first (&policy->rules);
400 BusPolicyRule *rule = link->data;
402 link = _dbus_list_get_next_link (&policy->rules, link);
404 /* Rule is skipped if it specifies a different service name from
408 if (rule->type != BUS_POLICY_RULE_OWN)
411 if (rule->d.own.service_name != NULL)
413 if (!_dbus_string_equal_c_str (service_name,
414 rule->d.own.service_name))
419 allowed = rule->allow;