]> git.ipfire.org Git - thirdparty/dbus.git/commitdiff
test: send_destination(_prefix) tests
authorAdrian Szyndela <adrian.s@samsung.com>
Thu, 25 Apr 2019 07:35:59 +0000 (09:35 +0200)
committerAdrian Szyndela <adrian.s@samsung.com>
Tue, 14 May 2019 08:31:12 +0000 (10:31 +0200)
This adds tests for mostly "send_destination_prefix" cases
and some "send_destination" cases.

The general test case is:
- addressed recipient is running and owns a name;
- a message is sent to the name owner;
- the response is checked for allow/deny (method return/error).
Each test case is executed both for primary and queued ownership.

The tests include:
- checking send allow/deny for names and namespaces, including nesting;
- checking send allow/deny for neighbour names;
- checking send allow/deny for names/namespaces+interface+member.

Signed-off-by: Adrian Szyndela <adrian.s@samsung.com>
Change-Id: If5fcada01601355e7aadefadad79c0b24f8c397f

test/Makefile.am
test/data/valid-config-files/send-destination-prefix-rules.conf.in [new file with mode: 0644]
test/dbus-daemon.c

index 559590b237b083b67d9f928d891c9919ca5785e5..fd16381cecddc95b6c1ce431e4a1122e7474ebdc 100644 (file)
@@ -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 \
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 (file)
index 0000000..304f05c
--- /dev/null
@@ -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: -->
index 8b012b9253f4473f793a1d927051775e5c2302df..80a79421ca3cdde8819f2b78e688e5d8b6af9ce0 100644 (file)
@@ -2210,6 +2210,267 @@ test_system_signals (Fixture *f,
 #endif
 #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)
@@ -2353,6 +2614,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)
@@ -2443,6 +2709,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;