summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon McVittie <simon.mcvittie@collabora.co.uk>2012-03-27 15:05:51 +0100
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2012-03-27 15:05:56 +0100
commita183a33fb5bceefe53d60d584f352ca0b61667e1 (patch)
treeb62feb8923a9dff08d48c26cf45db23639533c38
parent2460ddfdb2c1980226593e1af42117b38d5be7dc (diff)
parentf1cfc138efc2af0763a51ae665ea50096f613512 (diff)
downloaddbus-a183a33fb5bceefe53d60d584f352ca0b61667e1.tar.gz
Merge remote-tracking branch 'alban/own_prefix2'
Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk> Bug: https://bugs.freedesktop.org/show_bug.cgi?id=46273
-rw-r--r--bus/config-parser.c120
-rw-r--r--bus/policy.c47
-rw-r--r--bus/policy.h7
-rw-r--r--bus/services.c3
-rw-r--r--cmake/bus/dbus-daemon.xml8
-rw-r--r--doc/dbus-daemon.1.in10
-rw-r--r--test/data/valid-config-files/check-own-rules.conf14
-rw-r--r--test/data/valid-config-files/many-rules.conf2
8 files changed, 177 insertions, 34 deletions
diff --git a/bus/config-parser.c b/bus/config-parser.c
index a8953627..07e8fbb6 100644
--- a/bus/config-parser.c
+++ b/bus/config-parser.c
@@ -1154,6 +1154,7 @@ append_rule_from_element (BusConfigParser *parser,
const char *send_requested_reply;
const char *receive_requested_reply;
const char *own;
+ const char *own_prefix;
const char *user;
const char *group;
@@ -1179,6 +1180,7 @@ append_rule_from_element (BusConfigParser *parser,
"send_requested_reply", &send_requested_reply,
"receive_requested_reply", &receive_requested_reply,
"own", &own,
+ "own_prefix", &own_prefix,
"user", &user,
"group", &group,
"log", &log,
@@ -1190,7 +1192,7 @@ append_rule_from_element (BusConfigParser *parser,
receive_interface || receive_member || receive_error || receive_sender ||
receive_type || receive_path || eavesdrop ||
send_requested_reply || receive_requested_reply ||
- own || user || group))
+ own || own_prefix || user || group))
{
dbus_set_error (error, DBUS_ERROR_FAILED,
"Element <%s> must have one or more attributes",
@@ -1218,7 +1220,7 @@ append_rule_from_element (BusConfigParser *parser,
* base send_ can combine with send_destination, send_path, send_type, send_requested_reply
* base receive_ with receive_sender, receive_path, receive_type, receive_requested_reply, eavesdrop
*
- * user, group, own must occur alone
+ * user, group, own, own_prefix must occur alone
*
* Pretty sure the below stuff is broken, FIXME think about it more.
*/
@@ -1229,7 +1231,7 @@ append_rule_from_element (BusConfigParser *parser,
receive_error ||
receive_sender ||
receive_requested_reply ||
- own ||
+ own || own_prefix ||
user ||
group)) ||
@@ -1239,7 +1241,7 @@ append_rule_from_element (BusConfigParser *parser,
receive_error ||
receive_sender ||
receive_requested_reply ||
- own ||
+ own || own_prefix ||
user ||
group)) ||
@@ -1248,7 +1250,7 @@ append_rule_from_element (BusConfigParser *parser,
receive_error ||
receive_sender ||
receive_requested_reply ||
- own ||
+ own || own_prefix ||
user ||
group)) ||
@@ -1257,7 +1259,7 @@ append_rule_from_element (BusConfigParser *parser,
receive_error ||
receive_sender ||
receive_requested_reply ||
- own ||
+ own || own_prefix ||
user ||
group)) ||
@@ -1266,7 +1268,7 @@ append_rule_from_element (BusConfigParser *parser,
receive_error ||
receive_sender ||
receive_requested_reply ||
- own ||
+ own || own_prefix ||
user ||
group)) ||
@@ -1275,7 +1277,7 @@ append_rule_from_element (BusConfigParser *parser,
receive_error ||
receive_sender ||
receive_requested_reply ||
- own ||
+ own || own_prefix ||
user ||
group)) ||
@@ -1284,33 +1286,35 @@ append_rule_from_element (BusConfigParser *parser,
receive_error ||
receive_sender ||
receive_requested_reply ||
- own ||
+ own || own_prefix ||
user ||
group)) ||
(receive_interface && (receive_error ||
- own ||
+ own || own_prefix ||
user ||
group)) ||
(receive_member && (receive_error ||
- own ||
+ own || own_prefix ||
user ||
group)) ||
- (receive_error && (own ||
+ (receive_error && (own || own_prefix ||
user ||
group)) ||
- (eavesdrop && (own ||
+ (eavesdrop && (own || own_prefix ||
user ||
group)) ||
- (receive_requested_reply && (own ||
+ (receive_requested_reply && (own || own_prefix ||
user ||
group)) ||
- (own && (user || group)) ||
+ (own && (own_prefix || user || group)) ||
+
+ (own_prefix && (own || user || group)) ||
(user && group))
{
@@ -1488,18 +1492,29 @@ append_rule_from_element (BusConfigParser *parser,
if (receive_sender && rule->d.receive.origin == NULL)
goto nomem;
}
- else if (own)
+ else if (own || own_prefix)
{
rule = bus_policy_rule_new (BUS_POLICY_RULE_OWN, allow);
if (rule == NULL)
goto nomem;
- if (IS_WILDCARD (own))
- own = NULL;
+ if (own)
+ {
+ if (IS_WILDCARD (own))
+ own = NULL;
- rule->d.own.service_name = _dbus_strdup (own);
- if (own && rule->d.own.service_name == NULL)
- goto nomem;
+ rule->d.own.prefix = 0;
+ rule->d.own.service_name = _dbus_strdup (own);
+ if (own && rule->d.own.service_name == NULL)
+ goto nomem;
+ }
+ else
+ {
+ rule->d.own.prefix = 1;
+ rule->d.own.service_name = _dbus_strdup (own_prefix);
+ if (rule->d.own.service_name == NULL)
+ goto nomem;
+ }
}
else if (user)
{
@@ -2731,9 +2746,60 @@ typedef enum
} Validity;
static dbus_bool_t
+do_check_own_rules (BusPolicy *policy)
+{
+ const struct {
+ char *name;
+ dbus_bool_t allowed;
+ } checks[] = {
+ {"org.freedesktop", FALSE},
+ {"org.freedesktop.ManySystem", FALSE},
+ {"org.freedesktop.ManySystems", TRUE},
+ {"org.freedesktop.ManySystems.foo", TRUE},
+ {"org.freedesktop.ManySystems.foo.bar", TRUE},
+ {"org.freedesktop.ManySystems2", FALSE},
+ {"org.freedesktop.ManySystems2.foo", FALSE},
+ {"org.freedesktop.ManySystems2.foo.bar", FALSE},
+ {NULL, FALSE}
+ };
+ int i = 0;
+
+ while (checks[i].name)
+ {
+ DBusString service_name;
+ dbus_bool_t ret;
+
+ if (!_dbus_string_init (&service_name))
+ _dbus_assert_not_reached ("couldn't init string");
+ if (!_dbus_string_append (&service_name, checks[i].name))
+ _dbus_assert_not_reached ("couldn't append string");
+
+ ret = bus_policy_check_can_own (policy, &service_name);
+ printf (" Check name %s: %s\n", checks[i].name,
+ ret ? "allowed" : "not allowed");
+ if (checks[i].allowed && !ret)
+ {
+ _dbus_warn ("Cannot own %s\n", checks[i].name);
+ return FALSE;
+ }
+ if (!checks[i].allowed && ret)
+ {
+ _dbus_warn ("Can own %s\n", checks[i].name);
+ return FALSE;
+ }
+ _dbus_string_free (&service_name);
+
+ i++;
+ }
+
+ return TRUE;
+}
+
+static dbus_bool_t
do_load (const DBusString *full_path,
Validity validity,
- dbus_bool_t oom_possible)
+ dbus_bool_t oom_possible,
+ dbus_bool_t check_own_rules)
{
BusConfigParser *parser;
DBusError error;
@@ -2770,6 +2836,11 @@ do_load (const DBusString *full_path,
{
_DBUS_ASSERT_ERROR_IS_CLEAR (&error);
+ if (check_own_rules && do_check_own_rules (parser->policy) == FALSE)
+ {
+ return FALSE;
+ }
+
bus_config_parser_unref (parser);
if (validity == INVALID)
@@ -2786,6 +2857,7 @@ typedef struct
{
const DBusString *full_path;
Validity validity;
+ dbus_bool_t check_own_rules;
} LoaderOomData;
static dbus_bool_t
@@ -2793,7 +2865,7 @@ check_loader_oom_func (void *data)
{
LoaderOomData *d = data;
- return do_load (d->full_path, d->validity, TRUE);
+ return do_load (d->full_path, d->validity, TRUE, d->check_own_rules);
}
static dbus_bool_t
@@ -2876,6 +2948,8 @@ process_test_valid_subdir (const DBusString *test_base_dir,
d.full_path = &full_path;
d.validity = validity;
+ d.check_own_rules = _dbus_string_ends_with_c_str (&full_path,
+ "check-own-rules.conf");
/* FIXME hackaround for an expat problem, see
* https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=124747
diff --git a/bus/policy.c b/bus/policy.c
index 34e84469..379cea95 100644
--- a/bus/policy.c
+++ b/bus/policy.c
@@ -1240,25 +1240,26 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy,
return allowed;
}
-dbus_bool_t
-bus_client_policy_check_can_own (BusClientPolicy *policy,
- DBusConnection *connection,
- const DBusString *service_name)
+
+
+static dbus_bool_t
+bus_rules_check_can_own (DBusList *rules,
+ const DBusString *service_name)
{
DBusList *link;
dbus_bool_t allowed;
- /* policy->rules is in the order the rules appeared
+ /* rules is in the order the rules appeared
* in the config file, i.e. last rule that applies wins
*/
allowed = FALSE;
- link = _dbus_list_get_first_link (&policy->rules);
+ link = _dbus_list_get_first_link (&rules);
while (link != NULL)
{
BusPolicyRule *rule = link->data;
- link = _dbus_list_get_next_link (&policy->rules, link);
+ link = _dbus_list_get_next_link (&rules, link);
/* Rule is skipped if it specifies a different service name from
* the desired one.
@@ -1267,12 +1268,25 @@ bus_client_policy_check_can_own (BusClientPolicy *policy,
if (rule->type != BUS_POLICY_RULE_OWN)
continue;
- if (rule->d.own.service_name != NULL)
+ if (!rule->d.own.prefix && rule->d.own.service_name != NULL)
{
if (!_dbus_string_equal_c_str (service_name,
rule->d.own.service_name))
continue;
}
+ else if (rule->d.own.prefix)
+ {
+ const char *data;
+ char next_char;
+ if (!_dbus_string_starts_with_c_str (service_name,
+ rule->d.own.service_name))
+ continue;
+
+ data = _dbus_string_get_const_data (service_name);
+ next_char = data[strlen (rule->d.own.service_name)];
+ if (next_char != '\0' && next_char != '.')
+ continue;
+ }
/* Use this rule */
allowed = rule->allow;
@@ -1280,3 +1294,20 @@ bus_client_policy_check_can_own (BusClientPolicy *policy,
return allowed;
}
+
+dbus_bool_t
+bus_client_policy_check_can_own (BusClientPolicy *policy,
+ const DBusString *service_name)
+{
+ return bus_rules_check_can_own (policy->rules, service_name);
+}
+
+#ifdef DBUS_BUILD_TESTS
+dbus_bool_t
+bus_policy_check_can_own (BusPolicy *policy,
+ const DBusString *service_name)
+{
+ return bus_rules_check_can_own (policy->default_rules, service_name);
+}
+#endif /* DBUS_BUILD_TESTS */
+
diff --git a/bus/policy.h b/bus/policy.h
index 1782dbf3..3ff6f482 100644
--- a/bus/policy.h
+++ b/bus/policy.h
@@ -86,6 +86,8 @@ struct BusPolicyRule
{
/* can be NULL meaning "any" */
char *service_name;
+ /* if prefix is set, any name starting with service_name can be owned */
+ unsigned int prefix : 1;
} own;
struct
@@ -154,11 +156,14 @@ dbus_bool_t bus_client_policy_check_can_receive (BusClientPolicy *policy,
DBusMessage *message,
dbus_int32_t *toggles);
dbus_bool_t bus_client_policy_check_can_own (BusClientPolicy *policy,
- DBusConnection *connection,
const DBusString *service_name);
dbus_bool_t bus_client_policy_append_rule (BusClientPolicy *policy,
BusPolicyRule *rule);
void bus_client_policy_optimize (BusClientPolicy *policy);
+#ifdef DBUS_BUILD_TESTS
+dbus_bool_t bus_policy_check_can_own (BusPolicy *policy,
+ const DBusString *service_name);
+#endif
#endif /* BUS_POLICY_H */
diff --git a/bus/services.c b/bus/services.c
index 68a7022a..6f380fac 100644
--- a/bus/services.c
+++ b/bus/services.c
@@ -459,8 +459,7 @@ bus_registry_acquire_service (BusRegistry *registry,
goto out;
}
- if (!bus_client_policy_check_can_own (policy, connection,
- service_name))
+ if (!bus_client_policy_check_can_own (policy, service_name))
{
dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
"Connection \"%s\" is not allowed to own the service \"%s\" due "
diff --git a/cmake/bus/dbus-daemon.xml b/cmake/bus/dbus-daemon.xml
index c6f4db07..f331699c 100644
--- a/cmake/bus/dbus-daemon.xml
+++ b/cmake/bus/dbus-daemon.xml
@@ -512,6 +512,7 @@ statements, and works just like &lt;deny&gt; but with the inverse meaning.</para
eavesdrop="true" | "false"
own="name"
+ own_prefix="name"
user="username"
group="groupname"
</literallayout> <!-- .fi -->
@@ -590,6 +591,13 @@ the character "*" can be substituted, meaning "any." Complex globs
like "foo.bar.*" aren't allowed for now because they'd be work to
implement and maybe encourage sloppy security anyway.</para>
+<para>&lt;allow own_prefix="a.b"/&gt; allows you to own the name "a.b" or any
+name whose first dot-separated elements are "a.b": in particular,
+you can own "a.b.c" or "a.b.c.d", but not "a.bc" or "a.c".
+This is useful when services like Telepathy and ReserveDevice
+define a meaning for subtrees of well-known names, such as
+org.freedesktop.Telepathy.ConnectionManager.(anything)
+and org.freedesktop.ReserveDevice1.(anything).</para>
<para>It does not make sense to deny a user or group inside a &lt;policy&gt;
for a user or group; user/group denials can only be inside
diff --git a/doc/dbus-daemon.1.in b/doc/dbus-daemon.1.in
index b063e643..53856e91 100644
--- a/doc/dbus-daemon.1.in
+++ b/doc/dbus-daemon.1.in
@@ -501,6 +501,7 @@ The possible attributes of these elements are:
eavesdrop="true" | "false"
own="name"
+ own_prefix="name"
user="username"
group="groupname"
.fi
@@ -573,6 +574,15 @@ like "foo.bar.*" aren't allowed for now because they'd be work to
implement and maybe encourage sloppy security anyway.
.PP
+<allow own_prefix="a.b"/> allows you to own the name "a.b" or any
+name whose first dot-separated elements are "a.b": in particular,
+you can own "a.b.c" or "a.b.c.d", but not "a.bc" or "a.c".
+This is useful when services like Telepathy and ReserveDevice
+define a meaning for subtrees of well-known names, such as
+org.freedesktop.Telepathy.ConnectionManager.(anything)
+and org.freedesktop.ReserveDevice1.(anything).
+
+.PP
It does not make sense to deny a user or group inside a <policy>
for a user or group; user/group denials can only be inside
context="default" or context="mandatory" policies.
diff --git a/test/data/valid-config-files/check-own-rules.conf b/test/data/valid-config-files/check-own-rules.conf
new file mode 100644
index 00000000..bc2f415f
--- /dev/null
+++ b/test/data/valid-config-files/check-own-rules.conf
@@ -0,0 +1,14 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+ <user>mybususer</user>
+ <listen>unix:path=/foo/bar</listen>
+ <listen>tcp:port=1234</listen>
+ <servicedir>/usr/share/foo</servicedir>
+ <policy context="default">
+ <allow user="*"/>
+ <deny own="*"/>
+ <allow own_prefix="org.freedesktop.ManySystems"/>
+ </policy>
+
+</busconfig>
diff --git a/test/data/valid-config-files/many-rules.conf b/test/data/valid-config-files/many-rules.conf
index 089908b4..23931626 100644
--- a/test/data/valid-config-files/many-rules.conf
+++ b/test/data/valid-config-files/many-rules.conf
@@ -14,6 +14,7 @@
<deny receive_interface="org.freedesktop.System" receive_member="Reboot"/>
<deny send_path="/foo/bar/SystemObjectThing" send_member="Reboot"/>
<deny own="org.freedesktop.System"/>
+ <deny own_prefix="org.freedesktop.ManySystems"/>
<deny send_destination="org.freedesktop.System"/>
<deny receive_sender="org.freedesktop.System"/>
<deny user="root"/>
@@ -32,6 +33,7 @@
<deny receive_interface="org.freedesktop.System" receive_member="Reboot"/>
<deny send_path="/foo/bar/SystemObjectThing" send_member="Reboot"/>
<deny own="org.freedesktop.System"/>
+ <deny own_prefix="org.freedesktop.ManySystems"/>
<deny send_destination="org.freedesktop.System"/>
<deny receive_sender="org.freedesktop.System"/>
<deny user="root"/>