mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2026-02-15 18:30:28 +01:00
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
This commit is contained in:
commit
a183a33fb5
8 changed files with 177 additions and 34 deletions
|
|
@ -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)
|
||||
{
|
||||
|
|
@ -2730,10 +2745,61 @@ typedef enum
|
|||
UNKNOWN
|
||||
} 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
|
||||
|
|
|
|||
47
bus/policy.c
47
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 */
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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 "
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -501,6 +501,7 @@ The possible attributes of these elements are:
|
|||
eavesdrop="true" | "false"
|
||||
|
||||
own="name"
|
||||
own_prefix="name"
|
||||
user="username"
|
||||
group="groupname"
|
||||
.fi
|
||||
|
|
@ -572,6 +573,15 @@ 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.
|
||||
|
||||
.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
|
||||
|
|
|
|||
14
test/data/valid-config-files/check-own-rules.conf
Normal file
14
test/data/valid-config-files/check-own-rules.conf
Normal file
|
|
@ -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>
|
||||
|
|
@ -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"/>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue