diff options
author | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2012-03-27 15:05:51 +0100 |
---|---|---|
committer | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2012-03-27 15:05:56 +0100 |
commit | a183a33fb5bceefe53d60d584f352ca0b61667e1 (patch) | |
tree | b62feb8923a9dff08d48c26cf45db23639533c38 | |
parent | 2460ddfdb2c1980226593e1af42117b38d5be7dc (diff) | |
parent | f1cfc138efc2af0763a51ae665ea50096f613512 (diff) | |
download | dbus-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.c | 120 | ||||
-rw-r--r-- | bus/policy.c | 47 | ||||
-rw-r--r-- | bus/policy.h | 7 | ||||
-rw-r--r-- | bus/services.c | 3 | ||||
-rw-r--r-- | cmake/bus/dbus-daemon.xml | 8 | ||||
-rw-r--r-- | doc/dbus-daemon.1.in | 10 | ||||
-rw-r--r-- | test/data/valid-config-files/check-own-rules.conf | 14 | ||||
-rw-r--r-- | test/data/valid-config-files/many-rules.conf | 2 |
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 <deny> 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><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).</para> <para>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 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"/> |