summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon McVittie <smcv@collabora.com>2019-05-30 14:49:09 +0000
committerSimon McVittie <smcv@collabora.com>2019-05-30 14:49:09 +0000
commit463ecfb4fde5d7d30ce860f33dea596aa44d299e (patch)
treeaf28fd3c482a2df63446da88bb8734a18f418a7a
parentedece0274b37472d7da6db37e8afd9100d18564b (diff)
parentdcbab02613d38db4aad5a23ce7ac2505540078d1 (diff)
downloaddbus-463ecfb4fde5d7d30ce860f33dea596aa44d299e.tar.gz
Merge branch 'send_destination_prefix' into 'master'
Send destination prefix See merge request dbus/dbus!85
-rw-r--r--bus/config-parser.c29
-rw-r--r--bus/connection.c40
-rw-r--r--bus/connection.h4
-rw-r--r--bus/policy.c55
-rw-r--r--bus/policy.h1
-rw-r--r--dbus/dbus-string.c26
-rw-r--r--dbus/dbus-string.h4
-rw-r--r--doc/dbus-daemon.1.xml.in17
-rw-r--r--test/Makefile.am4
-rw-r--r--test/data/systemd-activation/com.example.SendPrefixDenied.SendPrefixAllowed.internal.service4
-rw-r--r--test/data/systemd-activation/com.example.SendPrefixDenied.internal.service4
-rw-r--r--test/data/systemd-activation/com.example.SendPrefixDenied.service4
-rw-r--r--test/data/valid-config-files/send-destination-prefix-rules.conf.in121
-rw-r--r--test/data/valid-config-files/systemd-activation.conf.in2
-rw-r--r--test/dbus-daemon.c269
-rw-r--r--test/sd-activation.c35
16 files changed, 603 insertions, 16 deletions
diff --git a/bus/config-parser.c b/bus/config-parser.c
index 4e62c342..a47b8a58 100644
--- a/bus/config-parser.c
+++ b/bus/config-parser.c
@@ -1298,6 +1298,7 @@ append_rule_from_element (BusConfigParser *parser,
const char *send_member;
const char *send_error;
const char *send_destination;
+ const char *send_destination_prefix;
const char *send_path;
const char *send_type;
const char *send_requested_reply;
@@ -1341,6 +1342,7 @@ append_rule_from_element (BusConfigParser *parser,
"send_member", &send_member,
"send_error", &send_error,
"send_destination", &send_destination,
+ "send_destination_prefix", &send_destination_prefix,
"send_path", &send_path,
"send_type", &send_type,
"send_broadcast", &send_broadcast,
@@ -1364,6 +1366,7 @@ append_rule_from_element (BusConfigParser *parser,
return FALSE;
any_send_attribute = (send_destination != NULL ||
+ send_destination_prefix != NULL ||
send_broadcast != NULL ||
send_path != NULL ||
send_type != NULL ||
@@ -1417,7 +1420,8 @@ append_rule_from_element (BusConfigParser *parser,
* interface + member
* error
*
- * base send_ can combine with send_destination, send_path, send_type, send_requested_reply, send_broadcast, eavesdrop
+ * base send_ can combine with send_destination, send_destination_prefix, send_path, send_type, send_requested_reply, send_broadcast, eavesdrop
+ * send_destination must not occur with send_destination_prefix
* base receive_ with receive_sender, receive_path, receive_type, receive_requested_reply, eavesdrop
*
* user, group, own, own_prefix must occur alone
@@ -1456,6 +1460,16 @@ append_rule_from_element (BusConfigParser *parser,
return FALSE;
}
+ if ((send_destination != NULL) + (send_destination_prefix != NULL) > 1)
+ {
+ dbus_set_error (error, DBUS_ERROR_FAILED,
+ "Invalid combination of attributes on element <%s>: "
+ "send_destination cannot be combined with "
+ "send_destination_prefix",
+ element_name);
+ return FALSE;
+ }
+
if ((receive_member != NULL || receive_interface != NULL) &&
receive_error != NULL)
{
@@ -1589,7 +1603,16 @@ append_rule_from_element (BusConfigParser *parser,
rule->d.send.interface = _dbus_strdup (send_interface);
rule->d.send.member = _dbus_strdup (send_member);
rule->d.send.error = _dbus_strdup (send_error);
- rule->d.send.destination = _dbus_strdup (send_destination);
+ if (send_destination)
+ {
+ rule->d.send.destination = _dbus_strdup (send_destination);
+ rule->d.send.destination_is_prefix = 0;
+ }
+ else if (send_destination_prefix)
+ {
+ rule->d.send.destination = _dbus_strdup (send_destination_prefix);
+ rule->d.send.destination_is_prefix = 1;
+ }
rule->d.send.max_fds = max_fds;
rule->d.send.min_fds = min_fds;
@@ -1601,7 +1624,7 @@ append_rule_from_element (BusConfigParser *parser,
goto nomem;
if (send_error && rule->d.send.error == NULL)
goto nomem;
- if (send_destination && rule->d.send.destination == NULL)
+ if ((send_destination || send_destination_prefix) && rule->d.send.destination == NULL)
goto nomem;
}
else if (any_receive_attribute)
diff --git a/bus/connection.c b/bus/connection.c
index 3af980d0..5943841d 100644
--- a/bus/connection.c
+++ b/bus/connection.c
@@ -1446,6 +1446,46 @@ bus_connection_get_n_match_rules (DBusConnection *connection)
return d->n_match_rules;
}
+/**
+ * Checks whether the connection owns any name with a given prefix,
+ * regardless of whether the type of ownership is primary or queued.
+ *
+ * @note A name matches to a prefix if it is equal to the prefix,
+ * or if it starts with the prefix followed by a dot. This is the same
+ * rule as the 'own_prefix' checking rule.
+ *
+ * @param connection the connection
+ * @param name_prefix the prefix
+ * @returns #TRUE if the connection owns at least one name with the prefix,
+ * regardless of the type of ownership
+ */
+dbus_bool_t
+bus_connection_is_name_owner_by_prefix (DBusConnection *connection,
+ const char *name_prefix)
+{
+ BusConnectionData *d;
+ DBusList *link;
+
+ d = BUS_CONNECTION_DATA (connection);
+ _dbus_assert (d != NULL);
+
+ link = _dbus_list_get_first_link (&d->services_owned);
+ while (link != NULL)
+ {
+ BusService *service = link->data;
+ DBusString str;
+
+ _dbus_string_init_const (&str, bus_service_get_name (service));
+
+ if (_dbus_string_starts_with_words_c_str (&str, name_prefix, '.'))
+ return TRUE;
+
+ link = _dbus_list_get_next_link (&d->services_owned, link);
+ }
+
+ return FALSE;
+}
+
void
bus_connection_add_owned_service_link (DBusConnection *connection,
DBusList *link)
diff --git a/bus/connection.h b/bus/connection.h
index 949a2231..912638c0 100644
--- a/bus/connection.h
+++ b/bus/connection.h
@@ -82,6 +82,10 @@ void bus_connection_send_oom_error (DBusConnection *connection,
void bus_connection_request_headers (DBusConnection *connection,
BusExtraHeaders headers);
+/* called by policy.c */
+dbus_bool_t bus_connection_is_name_owner_by_prefix (DBusConnection *connection,
+ const char *name_prefix);
+
/* called by signals.c */
dbus_bool_t bus_connection_add_match_rule (DBusConnection *connection,
BusMatchRule *rule);
diff --git a/bus/policy.c b/bus/policy.c
index c87bfecf..feb1156e 100644
--- a/bus/policy.c
+++ b/bus/policy.c
@@ -1018,7 +1018,7 @@ bus_client_policy_check_can_send (BusClientPolicy *policy,
}
}
- if (rule->d.send.destination != NULL)
+ if (rule->d.send.destination != NULL && !rule->d.send.destination_is_prefix)
{
/* receiver can be NULL for messages that are sent to the
* message bus itself, we check the strings in that case as
@@ -1044,9 +1044,9 @@ bus_client_policy_check_can_send (BusClientPolicy *policy,
{
DBusString str;
BusService *service;
-
+
_dbus_string_init_const (&str, rule->d.send.destination);
-
+
service = bus_registry_lookup (registry, &str);
if (service == NULL)
{
@@ -1064,6 +1064,43 @@ bus_client_policy_check_can_send (BusClientPolicy *policy,
}
}
+ if (rule->d.send.destination != NULL && rule->d.send.destination_is_prefix)
+ {
+ /* receiver can be NULL - the same as in !send.destination_is_prefix */
+ if (receiver == NULL)
+ {
+ const char *destination = dbus_message_get_destination (message);
+ DBusString dest_name;
+
+ if (destination == NULL)
+ {
+ _dbus_verbose (" (policy) skipping rule because message has no dest\n");
+ continue;
+ }
+
+ _dbus_string_init_const (&dest_name, destination);
+
+ if (!_dbus_string_starts_with_words_c_str (&dest_name,
+ rule->d.send.destination,
+ '.'))
+ {
+ _dbus_verbose (" (policy) skipping rule because message dest doesn't start with %s\n",
+ rule->d.send.destination);
+ continue;
+ }
+ }
+ else
+ {
+ if (!bus_connection_is_name_owner_by_prefix (receiver,
+ rule->d.send.destination))
+ {
+ _dbus_verbose (" (policy) skipping rule because no dest with prefix %s is owned by receiver\n",
+ rule->d.send.destination);
+ continue;
+ }
+ }
+ }
+
if (rule->d.send.min_fds > 0 ||
rule->d.send.max_fds < DBUS_MAXIMUM_MESSAGE_UNIX_FDS)
{
@@ -1341,15 +1378,9 @@ bus_rules_check_can_own (DBusList *rules,
}
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 != '.')
+ if (!_dbus_string_starts_with_words_c_str (service_name,
+ rule->d.own.service_name,
+ '.'))
continue;
}
diff --git a/bus/policy.h b/bus/policy.h
index 308eaf86..df59d090 100644
--- a/bus/policy.h
+++ b/bus/policy.h
@@ -76,6 +76,7 @@ struct BusPolicyRule
unsigned int requested_reply : 1;
unsigned int log : 1;
unsigned int broadcast : 2; /**< really a BusPolicyTristate */
+ unsigned int destination_is_prefix : 1;
} send;
struct
diff --git a/dbus/dbus-string.c b/dbus/dbus-string.c
index 52c71c5b..d620067e 100644
--- a/dbus/dbus-string.c
+++ b/dbus/dbus-string.c
@@ -2238,6 +2238,32 @@ _dbus_string_starts_with_c_str (const DBusString *a,
}
/**
+ * Checks whether a string starts with the given C string, after which it ends or is separated from
+ * the rest by a given separator character.
+ *
+ * @param a the string
+ * @param c_str the C string
+ * @param word_separator the separator
+ * @returns #TRUE if string starts with it
+ */
+dbus_bool_t
+_dbus_string_starts_with_words_c_str (const DBusString *a,
+ const char *c_str,
+ char word_separator)
+{
+ char next_char;
+ const char *data;
+ _dbus_assert (c_str != NULL);
+
+ if (!_dbus_string_starts_with_c_str (a, c_str))
+ return FALSE;
+
+ data = _dbus_string_get_const_data (a);
+ next_char = data[strlen (c_str)];
+ return next_char == '\0' || next_char == word_separator;
+}
+
+/**
* Appends a two-character hex digit to a string, where the hex digit
* has the value of the given byte.
*
diff --git a/dbus/dbus-string.h b/dbus/dbus-string.h
index 41e82ab9..7ac32d38 100644
--- a/dbus/dbus-string.h
+++ b/dbus/dbus-string.h
@@ -338,6 +338,10 @@ dbus_bool_t _dbus_string_starts_with_c_str (const DBusString *a,
dbus_bool_t _dbus_string_ends_with_c_str (const DBusString *a,
const char *c_str);
DBUS_PRIVATE_EXPORT
+dbus_bool_t _dbus_string_starts_with_words_c_str (const DBusString *a,
+ const char *c_str,
+ char word_separator);
+DBUS_PRIVATE_EXPORT
dbus_bool_t _dbus_string_pop_line (DBusString *source,
DBusString *dest);
DBUS_PRIVATE_EXPORT
diff --git a/doc/dbus-daemon.1.xml.in b/doc/dbus-daemon.1.xml.in
index acbc7ded..84698ca7 100644
--- a/doc/dbus-daemon.1.xml.in
+++ b/doc/dbus-daemon.1.xml.in
@@ -919,6 +919,7 @@ statements, and works just like &lt;deny&gt; but with the inverse meaning.</para
send_error="error_name" | "*"
send_broadcast="true" | "false"
send_destination="name" | "*"
+ send_destination_prefix="name"
send_type="method_call" | "method_return" | "signal" | "error" | "*"
send_path="/path/name" | "*"
@@ -998,6 +999,22 @@ will not work either. As a special case,
<literal>receive_sender="*"</literal> similarly matches any message.</para>
<para>
+ A <literal>send_destination_prefix</literal> rule opens or closes
+ the whole namespace for sending. It means that messages may or may not
+ be sent to the <emphasis>owner</emphasis> of any name matching the prefix, regardless of whether
+ it is the primary or the queued owner.
+ In other words, for <literal>&lt;allow send_destination_prefix="a.b"/&gt;</literal>
+ rule and names "a.b", "a.b.c", and "a.b.c.d" present on the bus, it works the same as
+ if three separate rules: <literal>&lt;allow send_destination="a.b"/&gt;</literal>,
+ <literal>&lt;allow send_destination="a.b.c"/&gt;</literal>, and
+ <literal>&lt;allow send_destination="a.b.c.d"/&gt;</literal> had been defined.
+ The rules for matching names are the same as in <literal>own_prefix</literal>
+ (see below): a prefix of "a.b" matches names "a.b" or "a.b.c" or "a.b.c.d", but not "a.bc"
+ or "a.c". The <literal>send_destination_prefix</literal> attribute cannot be combined
+ with the <literal>send_destination</literal> attribute in the same rule.
+</para>
+
+<para>
Rules with <literal>send_broadcast="true"</literal> match signal messages
with no destination (broadcasts). Rules with
<literal>send_broadcast="false"</literal> are the inverse: they match any
diff --git a/test/Makefile.am b/test/Makefile.am
index 559590b2..7547ea30 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -604,6 +604,7 @@ in_data = \
data/valid-config-files/max-replies-per-connection.conf.in \
data/valid-config-files/multi-user.conf.in \
data/valid-config-files/pending-fd-timeout.conf.in \
+ data/valid-config-files/send-destination-prefix-rules.conf.in \
data/valid-config-files/systemd-activation.conf.in \
data/valid-config-files/tmp-session.conf.in \
data/valid-config-files-system/tmp-session-like-system.conf.in \
@@ -687,6 +688,9 @@ static_data = \
data/systemd-activation/com.example.ReceiveDenied.service \
data/systemd-activation/com.example.SendDenied.service \
data/systemd-activation/com.example.SendDeniedByAppArmorName.service \
+ data/systemd-activation/com.example.SendPrefixDenied.service \
+ data/systemd-activation/com.example.SendPrefixDenied.internal.service \
+ data/systemd-activation/com.example.SendPrefixDenied.SendPrefixAllowed.internal.service \
data/systemd-activation/com.example.SystemdActivatable1.service \
data/systemd-activation/com.example.SystemdActivatable2.service \
data/systemd-activation/org.freedesktop.systemd1.service \
diff --git a/test/data/systemd-activation/com.example.SendPrefixDenied.SendPrefixAllowed.internal.service b/test/data/systemd-activation/com.example.SendPrefixDenied.SendPrefixAllowed.internal.service
new file mode 100644
index 00000000..5aab8bf2
--- /dev/null
+++ b/test/data/systemd-activation/com.example.SendPrefixDenied.SendPrefixAllowed.internal.service
@@ -0,0 +1,4 @@
+[D-BUS Service]
+Name=com.example.SendPrefixDenied.SendPrefixAllowed.internal
+Exec=/bin/false SendPrefixDenied.SendPrefixAllowed.internal
+SystemdService=dbus-com.example.SendPrefixDenied.SendPrefixAllowed.internal.service
diff --git a/test/data/systemd-activation/com.example.SendPrefixDenied.internal.service b/test/data/systemd-activation/com.example.SendPrefixDenied.internal.service
new file mode 100644
index 00000000..f9d63356
--- /dev/null
+++ b/test/data/systemd-activation/com.example.SendPrefixDenied.internal.service
@@ -0,0 +1,4 @@
+[D-BUS Service]
+Name=com.example.SendPrefixDenied.internal
+Exec=/bin/false SendPrefixDenied.internal
+SystemdService=dbus-com.example.SendPrefixDenied.internal.service
diff --git a/test/data/systemd-activation/com.example.SendPrefixDenied.service b/test/data/systemd-activation/com.example.SendPrefixDenied.service
new file mode 100644
index 00000000..3595ce19
--- /dev/null
+++ b/test/data/systemd-activation/com.example.SendPrefixDenied.service
@@ -0,0 +1,4 @@
+[D-BUS Service]
+Name=com.example.SendPrefixDenied
+Exec=/bin/false SendPrefixDenied
+SystemdService=dbus-com.example.SendPrefixDenied.service
diff --git a/test/data/valid-config-files/send-destination-prefix-rules.conf.in b/test/data/valid-config-files/send-destination-prefix-rules.conf.in
new file mode 100644
index 00000000..304f05c5
--- /dev/null
+++ b/test/data/valid-config-files/send-destination-prefix-rules.conf.in
@@ -0,0 +1,121 @@
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+ <listen>@TEST_LISTEN@</listen>
+ <policy context="default">
+ <allow user="*"/>
+ <deny own="*"/>
+ <deny send_type="method_call"/>
+ <allow send_type="signal"/>
+ <allow send_requested_reply="true" send_type="method_return"/>
+ <allow send_requested_reply="true" send_type="error"/>
+ <allow receive_type="method_call"/>
+ <allow receive_type="method_return"/>
+ <allow receive_type="error"/>
+ <allow receive_type="signal"/>
+ <allow send_destination="org.freedesktop.DBus"
+ send_interface="org.freedesktop.DBus" />
+ </policy>
+
+ <policy context="default">
+ <!-- deny the whole namespace first -->
+ <deny send_destination_prefix="foo.bar.test"/>
+ <!-- foo.bar.test.dest_prefix as a base for testing names -->
+ <allow own_prefix="foo.bar.test.dest_prefix"/>
+
+ <!-- abbreviations:
+ a - allow
+ d - deny
+ p - prefix
+ o - other
+ f - filler, no meaning, just for longer names
+ x - it's a trap!
+ -->
+ <!-- base allow -->
+ <allow send_destination_prefix="foo.bar.test.dest_prefix.ap"/>
+ <!-- a neighbour -->
+ <allow send_destination="foo.bar.test.dest_prefix.ao"/>
+
+ <!-- cut out some part of allowed space -->
+ <deny send_destination="foo.bar.test.dest_prefix.ap.f1.d"/>
+ <deny send_destination_prefix="foo.bar.test.dest_prefix.ap.f1.dp"/>
+
+ <!-- punch holes in the cutout -->
+ <allow send_destination_prefix="foo.bar.test.dest_prefix.ap.f1.d.ap"/>
+ <allow send_destination_prefix="foo.bar.test.dest_prefix.ap.f1.dp.ap"/>
+ <allow send_destination="foo.bar.test.dest_prefix.ap.f1.dp.a"/>
+
+ <!-- define something but redefine other way -->
+ <allow send_destination_prefix="foo.bar.test.dest_prefix.ap.f2.apxdp"/>
+ <deny send_destination_prefix="foo.bar.test.dest_prefix.ap.f2.apxdp.dp"/>
+ <allow send_destination_prefix="foo.bar.test.dest_prefix.ap.f2.apxdp.dp.ap"/>
+ <deny send_destination="foo.bar.test.dest_prefix.ap.f2.apxdp.dp.ap.d"/>
+ <!-- redefine -->
+ <deny send_destination_prefix="foo.bar.test.dest_prefix.ap.f2.apxdp"/>
+ <allow send_destination="foo.bar.test.dest_prefix.ap.f2.apxdp.dp.a"/>
+ <allow send_destination="foo.bar.test.dest_prefix.ap.f2.apxdp.dp.ap.f.a"/>
+ <allow send_destination_prefix="foo.bar.test.dest_prefix.ap.f2.apxdp.f.f.f.ap"/>
+
+ <!-- make something complicated but allow it at the end -->
+ <deny send_destination_prefix="foo.bar.test.dest_prefix.ap.f3.dpxap"/>
+ <allow send_destination_prefix="foo.bar.test.dest_prefix.ap.f3.dpxap.ap"/>
+ <deny send_destination_prefix="foo.bar.test.dest_prefix.ap.f3.dpxap.ap.dp"/>
+ <allow send_destination_prefix="foo.bar.test.dest_prefix.ap.f3.dpxap.ap.dp.ap"/>
+ <allow send_destination="foo.bar.test.dest_prefix.ap.f3.dpxap.ap.dp.a"/>
+ <allow send_destination_prefix="foo.bar.test.dest_prefix.ap.f3.dpxap"/>
+
+ <!-- base deny -->
+ <deny send_destination_prefix="foo.bar.test.dest_prefix.dp"/>
+
+ <!-- neighbours for base deny -->
+ <deny send_destination="foo.bar.test.dest_prefix.do"/>
+ <deny send_destination="foo.bar.test.dest_prefix.do.f"/>
+ <deny send_destination="foo.bar.test.dest_prefix.do.f.f"/>
+ <allow send_destination="foo.bar.test.dest_prefix.ao.ao"/>
+
+ <!-- cut out some part of allowed space -->
+ <allow send_destination="foo.bar.test.dest_prefix.dp.f1.a"/>
+ <allow send_destination_prefix="foo.bar.test.dest_prefix.dp.f1.ap"/>
+
+ <!-- punch holes in the cutout -->
+ <deny send_destination_prefix="foo.bar.test.dest_prefix.dp.f1.a.dp"/>
+ <deny send_destination_prefix="foo.bar.test.dest_prefix.dp.f1.ap.dp"/>
+ <deny send_destination="foo.bar.test.dest_prefix.dp.f1.ap.d"/>
+
+ <!-- define something but redefine other way -->
+ <deny send_destination_prefix="foo.bar.test.dest_prefix.dp.f2.dpxap"/>
+ <allow send_destination_prefix="foo.bar.test.dest_prefix.dp.f2.dpxap.ap"/>
+ <deny send_destination_prefix="foo.bar.test.dest_prefix.dp.f2.dpxap.ap.dp"/>
+ <allow send_destination="foo.bar.test.dest_prefix.dp.f2.dpxap.ap.dp.a"/>
+ <!-- redefine -->
+ <allow send_destination_prefix="foo.bar.test.dest_prefix.dp.f2.dpxap"/>
+ <deny send_destination="foo.bar.test.dest_prefix.dp.f2.dpxap.ap.d"/>
+ <deny send_destination="foo.bar.test.dest_prefix.dp.f2.dpxap.ap.dp.f.d"/>
+ <deny send_destination_prefix="foo.bar.test.dest_prefix.dp.f2.dpxap.f.f.f.dp"/>
+
+ <!-- make something complicated but deny it at the end -->
+ <allow send_destination_prefix="foo.bar.test.dest_prefix.dp.f3.apxdp"/>
+ <deny send_destination_prefix="foo.bar.test.dest_prefix.dp.f3.apxdp.dp"/>
+ <allow send_destination_prefix="foo.bar.test.dest_prefix.dp.f3.apxdp.dp.ap"/>
+ <deny send_destination_prefix="foo.bar.test.dest_prefix.dp.f3.apxdp.dp.ap.dp"/>
+ <deny send_destination="foo.bar.test.dest_prefix.dp.f3.apxdp.dp.ap.d"/>
+ <deny send_destination_prefix="foo.bar.test.dest_prefix.dp.f3.apxdp"/>
+
+ <!-- test send_destination_prefix with interface and method -->
+ <deny send_destination_prefix="foo.bar.test.dest_prefix.ap.m"
+ send_interface="foo.bar.a" send_member="CallDeny"/>
+ <deny send_destination_prefix="foo.bar.test.dest_prefix.ap.m"
+ send_interface="foo.bar.d"/>
+ <allow send_destination_prefix="foo.bar.test.dest_prefix.ap.m"
+ send_interface="foo.bar.d" send_member="CallAllow"/>
+
+ <allow send_destination_prefix="foo.bar.test.dest_prefix.dp.m"
+ send_interface="foo.bar.a"/>
+ <deny send_destination_prefix="foo.bar.test.dest_prefix.dp.m"
+ send_interface="foo.bar.a" send_member="CallDeny"/>
+ <allow send_destination_prefix="foo.bar.test.dest_prefix.dp.m"
+ send_interface="foo.bar.d" send_member="CallAllow"/>
+ </policy>
+
+</busconfig>
+<!-- vim: set ft=xml: -->
diff --git a/test/data/valid-config-files/systemd-activation.conf.in b/test/data/valid-config-files/systemd-activation.conf.in
index 2c3d2c21..499aaa59 100644
--- a/test/data/valid-config-files/systemd-activation.conf.in
+++ b/test/data/valid-config-files/systemd-activation.conf.in
@@ -14,6 +14,8 @@
<policy context="mandatory">
<deny send_destination="com.example.SendDenied"/>
+ <deny send_destination_prefix="com.example.SendPrefixDenied"/>
<deny receive_interface="com.example.ReceiveDenied" receive_member="Call"/>
+ <allow send_destination_prefix="com.example.SendPrefixDenied.SendPrefixAllowed"/>
</policy>
</busconfig>
diff --git a/test/dbus-daemon.c b/test/dbus-daemon.c
index 1e6946b7..66447955 100644
--- a/test/dbus-daemon.c
+++ b/test/dbus-daemon.c
@@ -2266,6 +2266,267 @@ test_system_signals (Fixture *f,
#endif
static void
+take_well_known_name (DBusConnection *conn,
+ const char *name,
+ DBusError *error,
+ int ownership_type)
+{
+ int ret = dbus_bus_request_name (conn, name, 0, error);
+ test_assert_no_error (error);
+ g_assert_cmpint (ret, ==, ownership_type);
+}
+
+static void
+drop_well_known_name (DBusConnection *conn,
+ const char *name,
+ DBusError *error)
+{
+ int ret = dbus_bus_release_name (conn, name, error);
+ test_assert_no_error (error);
+ g_assert_cmpint (ret, ==, DBUS_RELEASE_NAME_REPLY_RELEASED);
+}
+
+static void
+helper_send_destination_prefix_check (Fixture *f,
+ const char *name,
+ const char *interface,
+ const char *member,
+ dbus_bool_t allowed,
+ const char *additional_name,
+ int ownership_type)
+{
+ DBusMessage *call = NULL;
+ DBusMessage *reply = NULL;
+
+ take_well_known_name (f->right_conn, name, &f->e, ownership_type);
+
+ if (additional_name)
+ take_well_known_name (f->right_conn, additional_name, &f->e, ownership_type);
+
+ call = dbus_message_new_method_call (dbus_bus_get_unique_name (f->right_conn),
+ "/",
+ interface,
+ member);
+
+ if (call == NULL)
+ g_error ("OOM");
+
+ reply = test_main_context_call_and_wait (f->ctx, f->left_conn, call,
+ DBUS_TIMEOUT_USE_DEFAULT);
+ dbus_clear_message (&call);
+ g_test_message ("reply from %s(%d):%s OK", name, ownership_type, member);
+ if (allowed)
+ {
+ g_test_message ("checking reply from %s for correct method_return", name);
+ g_assert_cmpint (dbus_message_get_type (reply), ==,
+ DBUS_MESSAGE_TYPE_METHOD_RETURN);
+ }
+ else
+ {
+ g_test_message ("checking reply from %s for correct access_denied", name);
+ g_assert_cmpint (dbus_message_get_type (reply), ==,
+ DBUS_MESSAGE_TYPE_ERROR);
+ g_assert_cmpstr (dbus_message_get_error_name (reply), ==,
+ DBUS_ERROR_ACCESS_DENIED);
+ }
+ dbus_clear_message (&reply);
+
+ drop_well_known_name (f->right_conn, name, &f->e);
+
+ if (additional_name)
+ drop_well_known_name (f->right_conn, additional_name, &f->e);
+}
+
+static void
+helper_send_destination_prefix (Fixture *f,
+ const char *name,
+ const char *interface,
+ const char *member,
+ dbus_bool_t allowed,
+ const char *additional_name)
+{
+ /* check with primary ownership */
+ helper_send_destination_prefix_check (f, name, interface, member, allowed, additional_name, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
+
+ /* check with queued ownership */
+ take_well_known_name (f->left_conn, name, &f->e, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
+ if (additional_name)
+ take_well_known_name (f->left_conn, additional_name, &f->e, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
+
+ helper_send_destination_prefix_check (f, name, interface, member, allowed, additional_name, DBUS_REQUEST_NAME_REPLY_IN_QUEUE);
+
+ drop_well_known_name (f->left_conn, name, &f->e);
+ if (additional_name)
+ drop_well_known_name (f->left_conn, additional_name, &f->e);
+}
+
+static void
+test_send_destination_prefix (Fixture *f,
+ gconstpointer context G_GNUC_UNUSED)
+{
+ if (f->skip)
+ return;
+
+ add_echo_filter (f);
+
+ /*
+ * Names are constructed with prefix foo.bar.test.dest_prefix followed by some of the tokens:
+ * - a - allow send_destination for this name
+ * - d - deny send_destination for this name
+ * - ap - allow send_destination_prefix for this name
+ * - dp - deny send_destination_prefix for this name
+ * - f, f1, f2, f3 - fillers for generating names down the name hierarchy
+ * - apf, dpf, ao, do - just some neighbour names
+ * - m - names with 'm' have rules for interface and member
+ * - apxdp, dpxap - names that have contradicting rules, e.g. for apxdp there are "allow send_destination_prefix"
+ * rules first, followed by "deny send_destination_prefix" rules
+ */
+
+ /* basic checks - base allow */
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap", "com.example.Anything", "Anything", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f.f.f.f.f", "com.example.Anything", "Anything", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.apf", "com.example.Anything", "Anything", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.apf.f.f.f.f", "com.example.Anything", "Anything", FALSE, NULL);
+ /* basic checks - base deny */
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp", "com.example.Anything", "Anything", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f.f.f.f.f", "com.example.Anything", "Anything", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dpf", "com.example.Anything", "Anything", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dpf.f.f.f.f", "com.example.Anything", "Anything", FALSE, NULL);
+ /* With interface and method in the policy:
+ * everything is allowed, except foo.bar.a.CallDeny and whole foo.bar.d minus foo.bar.d.CallAllow.*/
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.m", "foo.bar.a", "CallDeny", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.m", "foo.bar.a", "CallAllow", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.m", "foo.bar.a", "NonExistent", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.m", "foo.bar.d", "CallDeny", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.m", "foo.bar.d", "CallAllow", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.m", "foo.bar.d", "NonExistent", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.m", "foo.bar.none", "NonExistent", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.m.f.f.f.f.f", "foo.bar.a", "CallDeny", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.m.f.f.f.f.f", "foo.bar.a", "CallAllow", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.m.f.f.f.f.f", "foo.bar.a", "NonExistent", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.m.f.f.f.f.f", "foo.bar.d", "CallDeny", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.m.f.f.f.f.f", "foo.bar.d", "CallAllow", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.m.f.f.f.f.f", "foo.bar.d", "NonExistent", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.m.f.f.f.f.f", "foo.bar.none", "NonExistent", TRUE, NULL);
+ /* With interface and method in the policy:
+ * everything is denied, except foo.bar.d.CallAllow and whole foo.bar.a minus foo.bar.a.CallDeny */
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.m", "foo.bar.a", "CallDeny", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.m", "foo.bar.a", "CallAllow", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.m", "foo.bar.a", "NonExistent", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.m", "foo.bar.d", "CallDeny", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.m", "foo.bar.d", "CallAllow", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.m", "foo.bar.d", "NonExistent", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.m", "foo.bar.none", "NonExistent", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.m.f.f.f.f.f", "foo.bar.a", "CallDeny", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.m.f.f.f.f.f", "foo.bar.a", "CallAllow", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.m.f.f.f.f.f", "foo.bar.a", "NonExistent", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.m.f.f.f.f.f", "foo.bar.d", "CallDeny", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.m.f.f.f.f.f", "foo.bar.d", "CallAllow", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.m.f.f.f.f.f", "foo.bar.d", "NonExistent", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.m.f.f.f.f.f", "foo.bar.none", "NonExistent", FALSE, NULL);
+ /* multiple names owned - everything is allowed */
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ao", "com.example.Anything", "Anything", TRUE, "foo.bar.test.dest_prefix.ap.f");
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f", "com.example.Anything", "Anything", TRUE, "foo.bar.test.dest_prefix.ao");
+ /* multiple names owned - mixed allow/deny, but denied wins */
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f", "com.example.Anything", "Anything", FALSE, "foo.bar.test.dest_prefix.ap.f");
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f", "com.example.Anything", "Anything", FALSE, "foo.bar.test.dest_prefix.dp.f");
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.do", "com.example.Anything", "Anything", FALSE, "foo.bar.test.dest_prefix.ap.f");
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f", "com.example.Anything", "Anything", FALSE, "foo.bar.test.dest_prefix.do");
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ao", "com.example.Anything", "Anything", FALSE, "foo.bar.test.dest_prefix.dp.f");
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f", "com.example.Anything", "Anything", FALSE, "foo.bar.test.dest_prefix.ao");
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f.f", "com.example.Anything", "Anything", FALSE, "foo.bar.test.dest_prefix.ao.f");
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ao.f", "com.example.Anything", "Anything", FALSE, "foo.bar.test.dest_prefix.dp.f.f");
+ /* multiple names owned - mixed allow/deny, but allowed wins */
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f", "com.example.Anything", "Anything", TRUE, "foo.bar.test.dest_prefix.ao.ao");
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ao.ao", "com.example.Anything", "Anything", TRUE, "foo.bar.test.dest_prefix.dp.f");
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f", "com.example.Anything", "Anything", TRUE, "foo.bar.test.dest_prefix.dp.f1.ap.f");
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f1.ap.f", "com.example.Anything", "Anything", TRUE, "foo.bar.test.dest_prefix.dp.f");
+ /* multiple names owned - everything is denied */
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f", "com.example.Anything", "Anything", FALSE, "foo.bar.test.dest_prefix.do.f");
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.do.f", "com.example.Anything", "Anything", FALSE, "foo.bar.test.dest_prefix.dp.f");
+ /* holes in default allow */
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f1.d", "com.example.Anything", "Anything", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f1.dp", "com.example.Anything", "Anything", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f1.dp.f.f.f.f", "com.example.Anything", "Anything", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f1.dp.f.f.f.f", "com.example.Anything", "Anything", FALSE, "foo.bar.test.dest_prefix.ao");
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f1.dp.f.f.f.f", "com.example.Anything", "Anything", FALSE, "foo.bar.test.dest_prefix.ap");
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ao", "com.example.Anything", "Anything", FALSE, "foo.bar.test.dest_prefix.ap.f1.dp.f.f.f.f");
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap", "com.example.Anything", "Anything", FALSE, "foo.bar.test.dest_prefix.ap.f1.dp.f.f.f.f");
+ /* holes in holes in default allow */
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f1.d.ap", "com.example.Anything", "Anything", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f1.d.ap.f.f.f.f", "com.example.Anything", "Anything", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f1.dp.ap", "com.example.Anything", "Anything", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f1.dp.ap.f.f.f.f", "com.example.Anything", "Anything", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f1.dp.ap.a", "com.example.Anything", "Anything", TRUE, NULL);
+ /* redefinitions in default allow */
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f2.apxdp", "com.example.Anything", "Anything", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f2.apxdp.f.f.f.f", "com.example.Anything", "Anything", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f2.apxdp.dp", "com.example.Anything", "Anything", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f2.apxdp.dp.f.f.f.f", "com.example.Anything", "Anything", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f2.apxdp.dp.ap", "com.example.Anything", "Anything", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f2.apxdp.dp.ap.f.f.f.f", "com.example.Anything", "Anything", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f2.apxdp.dp.ap.d", "com.example.Anything", "Anything", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f2.apxdp.dp.a", "com.example.Anything", "Anything", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f2.apxdp.dp.ap.f.a", "com.example.Anything", "Anything", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f2.apxdp.f.f.f.ap", "com.example.Anything", "Anything", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f2.apxdp.f.f.f.ap.f.f.f", "com.example.Anything", "Anything", TRUE, NULL);
+ /* cancelled definitions in default allow */
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f3.dpxap", "com.example.Anything", "Anything", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f3.dpxap.f.f.f.f", "com.example.Anything", "Anything", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f3.dpxap.ap", "com.example.Anything", "Anything", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f3.dpxap.ap.f.f.f", "com.example.Anything", "Anything", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f3.dpxap.ap.dp", "com.example.Anything", "Anything", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f3.dpxap.ap.dp.f.f.f.f", "com.example.Anything", "Anything", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f3.dpxap.ap.dp.ap", "com.example.Anything", "Anything", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f3.dpxap.ap.dp.ap.f.f.f.f", "com.example.Anything", "Anything", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ap.f3.dpxap.ap.dp.a", "com.example.Anything", "Anything", TRUE, NULL);
+ /* holes in default deny */
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f1.a", "com.example.Anything", "Anything", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f1.a.f.f.f.f", "com.example.Anything", "Anything", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f1.ap", "com.example.Anything", "Anything", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f1.ap.f.f.f.f", "com.example.Anything", "Anything", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f1.ap.f.f.f", "com.example.Anything", "Anything", TRUE, "foo.bar.test.dest_prefix.do");
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.do", "com.example.Anything", "Anything", TRUE, "foo.bar.test.dest_prefix.dp.f1.ap.f.f.f");
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f1.ap.f.f.f", "com.example.Anything", "Anything", TRUE, "foo.bar.test.dest_prefix.do.f.f");
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.do.f.f", "com.example.Anything", "Anything", TRUE, "foo.bar.test.dest_prefix.dp.f1.ap.f.f.f");
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f1.ap.f.f", "com.example.Anything", "Anything", TRUE, "foo.bar.test.dest_prefix.dp.f.f.f");
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f.f.f", "com.example.Anything", "Anything", TRUE, "foo.bar.test.dest_prefix.dp.f1.ap.f.f");
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.ao", "com.example.Anything", "Anything", TRUE, NULL);
+ /* holes in holes in default deny */
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f1.a.dp", "com.example.Anything", "Anything", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f1.a.dp.f.f.f.f", "com.example.Anything", "Anything", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f1.ap.dp", "com.example.Anything", "Anything", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f1.ap.dp.f.f.f.f", "com.example.Anything", "Anything", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f1.ap.d", "com.example.Anything", "Anything", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f1.ap.d.f.f.f.f", "com.example.Anything", "Anything", TRUE, NULL);
+ /* redefinitions in default deny */
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f2.dpxap", "com.example.Anything", "Anything", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f2.dpxap.f.f.f.f", "com.example.Anything", "Anything", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f2.dpxap.ap", "com.example.Anything", "Anything", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f2.dpxap.ap.f.f.f.f", "com.example.Anything", "Anything", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f2.dpxap.ap.dp", "com.example.Anything", "Anything", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f2.dpxap.ap.dp.f.f.f.f", "com.example.Anything", "Anything", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f2.dpxap.ap.dp.a", "com.example.Anything", "Anything", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f2.dpxap.ap.dp.a.f.f.f", "com.example.Anything", "Anything", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f2.dpxap.ap.d", "com.example.Anything", "Anything", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f2.dpxap.ap.d.f.f.f", "com.example.Anything", "Anything", TRUE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f2.dpxap.ap.dp.f.d", "com.example.Anything", "Anything", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f2.dpxap.f.f.f.dp", "com.example.Anything", "Anything", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f2.dpxap.f.f.f.dp.f.f.f", "com.example.Anything", "Anything", FALSE, NULL);
+ /* cancelled definitions in default deny */
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f3.apxdp", "com.example.Anything", "Anything", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f3.apxdp.f.f.f.f", "com.example.Anything", "Anything", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f3.apxdp.dp", "com.example.Anything", "Anything", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f3.apxdp.dp.f.f.f.f", "com.example.Anything", "Anything", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f3.apxdp.dp.ap", "com.example.Anything", "Anything", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f3.apxdp.dp.ap.f.f.f.f", "com.example.Anything", "Anything", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f3.apxdp.dp.ap.dp", "com.example.Anything", "Anything", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f3.apxdp.dp.ap.dp.f.f.f.f", "com.example.Anything", "Anything", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f3.apxdp.dp.ap.d", "com.example.Anything", "Anything", FALSE, NULL);
+ helper_send_destination_prefix (f, "foo.bar.test.dest_prefix.dp.f3.apxdp.dp.ap.d.f.f.f.f", "com.example.Anything", "Anything", FALSE, NULL);
+}
+
+static void
teardown (Fixture *f,
gconstpointer context G_GNUC_UNUSED)
{
@@ -2408,6 +2669,11 @@ static Config nearly_system_config = {
#endif
#endif
+static Config send_destination_prefix_config = {
+ NULL, 1, "valid-config-files/send-destination-prefix-rules.conf",
+ TEST_USER_ME, SPECIFY_ADDRESS
+};
+
int
main (int argc,
char **argv)
@@ -2498,6 +2764,9 @@ main (int argc,
#endif
#endif
+ g_test_add ("/system-policy/send-destination/prefix", Fixture, &send_destination_prefix_config,
+ setup, test_send_destination_prefix, teardown);
+
ret = g_test_run ();
dbus_shutdown ();
return ret;
diff --git a/test/sd-activation.c b/test/sd-activation.c
index b60888ae..e02e3013 100644
--- a/test/sd-activation.c
+++ b/test/sd-activation.c
@@ -516,6 +516,37 @@ test_activation (Fixture *f,
g_error ("OOM");
dbus_connection_send (f->systemd, m, NULL);
dbus_message_unref (m);
+
+ /* A fourth activation: for name from send_destination_prefix namespace */
+ m = dbus_message_new_signal ("/foo", "com.example.bar", "UnicastSignal4");
+ if (!dbus_message_set_destination (m, "com.example.SendPrefixDenied.SendPrefixAllowed.internal"))
+ g_error ("OOM");
+ dbus_connection_send (f->caller, m, NULL);
+ dbus_message_unref (m);
+
+ /* systemd is already ready for it. */
+ while (f->systemd_message == NULL)
+ test_main_context_iterate (f->ctx, TRUE);
+
+ m = f->systemd_message;
+ f->systemd_message = NULL;
+ assert_signal (m, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS,
+ "org.freedesktop.systemd1.Activator", "ActivationRequest", "s",
+ "org.freedesktop.systemd1");
+
+ /* Check ActivationRequest for the required name. */
+ /* If it is correct, then it passed through policy checking, and the test is over. */
+ do
+ {
+ const char *name;
+ DBusError error;
+
+ dbus_error_init (&error);
+ dbus_message_get_args (m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID);
+ test_assert_no_error (&error);
+ g_assert_cmpstr (name, ==, "dbus-com.example.SendPrefixDenied.SendPrefixAllowed.internal.service");
+ } while (0);
+ dbus_message_unref (m);
}
static void
@@ -1031,7 +1062,9 @@ static const Config deny_send_tests[] =
{ "com.example.SendDeniedByNonexistentAppArmorLabel" },
{ "com.example.SendDeniedByAppArmorName" },
#endif
- { "com.example.SendDenied" }
+ { "com.example.SendDenied" },
+ { "com.example.SendPrefixDenied" },
+ { "com.example.SendPrefixDenied.internal" }
};
static const Config deny_receive_tests[] =