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 link = _dbus_list_get_first (&policy->rules);
181 BusPolicyRule *rule = link->data;
182 DBusList *next = _dbus_list_get_next_link (&policy->rules, link);
183 dbus_bool_t remove_preceding;
185 remove_preceding = FALSE;
189 case BUS_POLICY_RULE_SEND:
191 rule->d.send.message_name == NULL &&
192 rule->d.send.destination == NULL;
194 case BUS_POLICY_RULE_RECEIVE:
196 rule->d.receive.message_name == NULL &&
197 rule->d.receive.origin == NULL;
199 case BUS_POLICY_RULE_OWN:
201 rule->d.own.service_name == NULL;
205 if (remove_preceding)
206 remove_rules_by_type_up_to (policy, rule->type,
214 bus_policy_check_can_send (BusPolicy *policy,
215 BusRegistry *registry,
216 DBusConnection *receiver,
217 DBusMessage *message)
222 /* policy->rules is in the order the rules appeared
223 * in the config file, i.e. last rule that applies wins
227 link = _dbus_list_get_first (&policy->rules);
230 BusPolicyRule *rule = link->data;
232 link = _dbus_list_get_next_link (&policy->rules, link);
234 /* Rule is skipped if it specifies a different
235 * message name from the message, or a different
236 * destination from the message
239 if (rule->type != BUS_POLICY_RULE_SEND)
242 if (rule->d.send.message_name != NULL)
244 if (!dbus_message_name_is (message,
245 rule->d.send.message_name))
249 if (rule->d.send.destination != NULL)
251 /* receiver can be NULL for messages that are sent to the
252 * message bus itself, we check the strings in that case as
253 * built-in services don't have a DBusConnection but messages
254 * to them have a destination service name.
256 if (receiver == NULL)
258 if (!dbus_message_sender_is (message,
259 rule->d.send.destination))
267 _dbus_string_init_const (&str, rule->d.send.destination);
269 service = bus_registry_lookup (registry, &str);
273 if (!bus_service_has_owner (service, receiver))
279 allowed = rule->allow;
286 bus_policy_check_can_receive (BusPolicy *policy,
287 BusRegistry *registry,
288 DBusConnection *sender,
289 DBusMessage *message)
294 /* policy->rules is in the order the rules appeared
295 * in the config file, i.e. last rule that applies wins
299 link = _dbus_list_get_first (&policy->rules);
302 BusPolicyRule *rule = link->data;
304 link = _dbus_list_get_next_link (&policy->rules, link);
306 /* Rule is skipped if it specifies a different
307 * message name from the message, or a different
308 * origin from the message
311 if (rule->type != BUS_POLICY_RULE_RECEIVE)
314 if (rule->d.receive.message_name != NULL)
316 if (!dbus_message_name_is (message,
317 rule->d.receive.message_name))
321 if (rule->d.receive.origin != NULL)
323 /* sender can be NULL for messages that originate from the
324 * message bus itself, we check the strings in that case as
325 * built-in services don't have a DBusConnection but will
326 * still set the sender on their messages.
330 if (!dbus_message_sender_is (message,
331 rule->d.receive.origin))
339 _dbus_string_init_const (&str, rule->d.receive.origin);
341 service = bus_registry_lookup (registry, &str);
346 if (!bus_service_has_owner (service, sender))
352 allowed = rule->allow;
359 bus_policy_check_can_own (BusPolicy *policy,
360 DBusConnection *connection,
361 const DBusString *service_name)
366 /* policy->rules is in the order the rules appeared
367 * in the config file, i.e. last rule that applies wins
371 link = _dbus_list_get_first (&policy->rules);
374 BusPolicyRule *rule = link->data;
376 link = _dbus_list_get_next_link (&policy->rules, link);
378 /* Rule is skipped if it specifies a different service name from
382 if (rule->type != BUS_POLICY_RULE_OWN)
385 if (rule->d.own.service_name != NULL)
387 if (!_dbus_string_equal_c_str (service_name,
388 rule->d.own.service_name))
393 allowed = rule->allow;