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);
94 policy = dbus_new0 (BusPolicy, 1);
104 bus_policy_ref (BusPolicy *policy)
106 _dbus_assert (policy->refcount > 0);
108 policy->refcount += 1;
112 rule_unref_foreach (void *data,
115 BusPolicyRule *rule = data;
117 bus_policy_rule_unref (rule);
121 bus_policy_unref (BusPolicy *policy)
123 _dbus_assert (policy->refcount > 0);
125 policy->refcount -= 1;
127 if (policy->refcount == 0)
129 _dbus_list_foreach (&policy->rules,
133 _dbus_list_clear (&policy->rules);
140 remove_rules_by_type_up_to (BusPolicy *policy,
141 BusPolicyRuleType type,
146 link = _dbus_list_get_first (&policy->rules);
147 while (link != up_to)
149 BusPolicyRule *rule = link->data;
150 DBusList *next = _dbus_list_get_next_link (&policy->rules, link);
152 bus_policy_rule_unref (rule);
153 _dbus_list_remove_link (&policy->rules, link);
160 bus_policy_optimize (BusPolicy *policy)
164 /* The idea here is that if we have:
166 * <allow send="foo"/>
169 * (for example) the deny will always override the allow. So we
170 * delete the allow. Ditto for deny followed by allow, etc. This is
171 * a dumb thing to put in a config file, but the <include> feature
172 * of files allows for an "inheritance and override" pattern where
173 * it could make sense. If an included file wants to "start over"
174 * with a blanket deny, no point keeping the rules from the parent
178 _dbus_verbose ("Optimizing policy with %d rules\n",
179 _dbus_list_get_length (&policy->rules));
181 link = _dbus_list_get_first (&policy->rules);
184 BusPolicyRule *rule = link->data;
185 DBusList *next = _dbus_list_get_next_link (&policy->rules, link);
186 dbus_bool_t remove_preceding;
188 remove_preceding = FALSE;
192 case BUS_POLICY_RULE_SEND:
194 rule->d.send.message_name == NULL &&
195 rule->d.send.destination == NULL;
197 case BUS_POLICY_RULE_RECEIVE:
199 rule->d.receive.message_name == NULL &&
200 rule->d.receive.origin == NULL;
202 case BUS_POLICY_RULE_OWN:
204 rule->d.own.service_name == NULL;
208 if (remove_preceding)
209 remove_rules_by_type_up_to (policy, rule->type,
215 _dbus_verbose ("After optimization, policy has %d rules\n",
216 _dbus_list_get_length (&policy->rules));
220 bus_policy_append_rule (BusPolicy *policy,
223 if (!_dbus_list_append (policy->rules, rule))
226 bus_policy_rule_ref (rule);
232 bus_policy_check_can_send (BusPolicy *policy,
233 BusRegistry *registry,
234 DBusConnection *receiver,
235 DBusMessage *message)
240 /* policy->rules is in the order the rules appeared
241 * in the config file, i.e. last rule that applies wins
245 link = _dbus_list_get_first (&policy->rules);
248 BusPolicyRule *rule = link->data;
250 link = _dbus_list_get_next_link (&policy->rules, link);
252 /* Rule is skipped if it specifies a different
253 * message name from the message, or a different
254 * destination from the message
257 if (rule->type != BUS_POLICY_RULE_SEND)
260 if (rule->d.send.message_name != NULL)
262 if (!dbus_message_name_is (message,
263 rule->d.send.message_name))
267 if (rule->d.send.destination != NULL)
269 /* receiver can be NULL for messages that are sent to the
270 * message bus itself, we check the strings in that case as
271 * built-in services don't have a DBusConnection but messages
272 * to them have a destination service name.
274 if (receiver == NULL)
276 if (!dbus_message_sender_is (message,
277 rule->d.send.destination))
285 _dbus_string_init_const (&str, rule->d.send.destination);
287 service = bus_registry_lookup (registry, &str);
291 if (!bus_service_has_owner (service, receiver))
297 allowed = rule->allow;
304 bus_policy_check_can_receive (BusPolicy *policy,
305 BusRegistry *registry,
306 DBusConnection *sender,
307 DBusMessage *message)
312 /* policy->rules is in the order the rules appeared
313 * in the config file, i.e. last rule that applies wins
317 link = _dbus_list_get_first (&policy->rules);
320 BusPolicyRule *rule = link->data;
322 link = _dbus_list_get_next_link (&policy->rules, link);
324 /* Rule is skipped if it specifies a different
325 * message name from the message, or a different
326 * origin from the message
329 if (rule->type != BUS_POLICY_RULE_RECEIVE)
332 if (rule->d.receive.message_name != NULL)
334 if (!dbus_message_name_is (message,
335 rule->d.receive.message_name))
339 if (rule->d.receive.origin != NULL)
341 /* sender can be NULL for messages that originate from the
342 * message bus itself, we check the strings in that case as
343 * built-in services don't have a DBusConnection but will
344 * still set the sender on their messages.
348 if (!dbus_message_sender_is (message,
349 rule->d.receive.origin))
357 _dbus_string_init_const (&str, rule->d.receive.origin);
359 service = bus_registry_lookup (registry, &str);
364 if (!bus_service_has_owner (service, sender))
370 allowed = rule->allow;
377 bus_policy_check_can_own (BusPolicy *policy,
378 DBusConnection *connection,
379 const DBusString *service_name)
384 /* policy->rules is in the order the rules appeared
385 * in the config file, i.e. last rule that applies wins
389 link = _dbus_list_get_first (&policy->rules);
392 BusPolicyRule *rule = link->data;
394 link = _dbus_list_get_next_link (&policy->rules, link);
396 /* Rule is skipped if it specifies a different service name from
400 if (rule->type != BUS_POLICY_RULE_OWN)
403 if (rule->d.own.service_name != NULL)
405 if (!_dbus_string_equal_c_str (service_name,
406 rule->d.own.service_name))
411 allowed = rule->allow;