diff options
author | Simon McVittie <smcv@collabora.com> | 2019-05-30 14:49:09 +0000 |
---|---|---|
committer | Simon McVittie <smcv@collabora.com> | 2019-05-30 14:49:09 +0000 |
commit | 463ecfb4fde5d7d30ce860f33dea596aa44d299e (patch) | |
tree | af28fd3c482a2df63446da88bb8734a18f418a7a | |
parent | edece0274b37472d7da6db37e8afd9100d18564b (diff) | |
parent | dcbab02613d38db4aad5a23ce7ac2505540078d1 (diff) | |
download | dbus-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.c | 29 | ||||
-rw-r--r-- | bus/connection.c | 40 | ||||
-rw-r--r-- | bus/connection.h | 4 | ||||
-rw-r--r-- | bus/policy.c | 55 | ||||
-rw-r--r-- | bus/policy.h | 1 | ||||
-rw-r--r-- | dbus/dbus-string.c | 26 | ||||
-rw-r--r-- | dbus/dbus-string.h | 4 | ||||
-rw-r--r-- | doc/dbus-daemon.1.xml.in | 17 | ||||
-rw-r--r-- | test/Makefile.am | 4 | ||||
-rw-r--r-- | test/data/systemd-activation/com.example.SendPrefixDenied.SendPrefixAllowed.internal.service | 4 | ||||
-rw-r--r-- | test/data/systemd-activation/com.example.SendPrefixDenied.internal.service | 4 | ||||
-rw-r--r-- | test/data/systemd-activation/com.example.SendPrefixDenied.service | 4 | ||||
-rw-r--r-- | test/data/valid-config-files/send-destination-prefix-rules.conf.in | 121 | ||||
-rw-r--r-- | test/data/valid-config-files/systemd-activation.conf.in | 2 | ||||
-rw-r--r-- | test/dbus-daemon.c | 269 | ||||
-rw-r--r-- | test/sd-activation.c | 35 |
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 <deny> 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><allow send_destination_prefix="a.b"/></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><allow send_destination="a.b"/></literal>, + <literal><allow send_destination="a.b.c"/></literal>, and + <literal><allow send_destination="a.b.c.d"/></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[] = |