Add tests for activation when message send/receive is denied 06/193006/2
authorSimon McVittie <simon.mcvittie@collabora.co.uk>
Fri, 16 Oct 2015 16:33:36 +0000 (17:33 +0100)
committerHyotaek Shim <hyotaek.shim@samsung.com>
Thu, 15 Nov 2018 03:18:49 +0000 (03:18 +0000)
Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
Reviewed-by: Philip Withnall <philip.withnall@collabora.co.uk>
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=98666

Change-Id: I7339c1a6de69a751cbe0b9047c980c4aea53750b

test/Makefile.am
test/data/systemd-activation/com.example.ReceiveDenied.service [new file with mode: 0644]
test/data/systemd-activation/com.example.SendDenied.service [new file with mode: 0644]
test/data/valid-config-files/systemd-activation.conf.in
test/sd-activation.c

index 1f4c8fe..cd4d1e7 100644 (file)
@@ -376,6 +376,8 @@ static_data = \
        data/sha-1/bit-messages.sha1 \
        data/sha-1/byte-hashes.sha1 \
        data/sha-1/byte-messages.sha1 \
+       data/systemd-activation/com.example.ReceiveDenied.service \
+       data/systemd-activation/com.example.SendDenied.service \
        data/systemd-activation/com.example.SystemdActivatable1.service \
        data/systemd-activation/com.example.SystemdActivatable2.service \
        data/systemd-activation/com.example.SystemdActivatable3.service \
diff --git a/test/data/systemd-activation/com.example.ReceiveDenied.service b/test/data/systemd-activation/com.example.ReceiveDenied.service
new file mode 100644 (file)
index 0000000..a4944f7
--- /dev/null
@@ -0,0 +1,4 @@
+[D-BUS Service]
+Name=com.example.ReceiveDenied
+Exec=/bin/false ReceiveDenied
+SystemdService=dbus-com.example.ReceiveDenied.service
diff --git a/test/data/systemd-activation/com.example.SendDenied.service b/test/data/systemd-activation/com.example.SendDenied.service
new file mode 100644 (file)
index 0000000..aa9eb78
--- /dev/null
@@ -0,0 +1,4 @@
+[D-BUS Service]
+Name=com.example.SendDenied
+Exec=/bin/false SendDenied
+SystemdService=dbus-com.example.SendDenied.service
index bcd6416..a3a59f0 100644 (file)
@@ -3,9 +3,15 @@
 <busconfig>
   <listen>@TEST_LISTEN@</listen>
   <servicedir>@DBUS_TEST_DATA@/systemd-activation</servicedir>
+
   <policy context="default">
     <allow send_destination="*"/>
     <allow receive_sender="*"/>
     <allow own="*"/>
   </policy>
+
+  <policy context="mandatory">
+    <deny send_destination="com.example.SendDenied"/>
+    <deny receive_interface="com.example.ReceiveDenied" receive_member="Call"/>
+  </policy>
 </busconfig>
index f045012..6d52987 100644 (file)
@@ -40,12 +40,18 @@ typedef struct {
 
     DBusConnection *caller;
     const char *caller_name;
+    DBusMessage *caller_message;
+    dbus_bool_t caller_filter_added;
+
     DBusConnection *systemd;
     const char *systemd_name;
     DBusMessage *systemd_message;
+    dbus_bool_t systemd_filter_added;
+
     DBusConnection *activated;
     const char *activated_name;
     DBusMessage *activated_message;
+    dbus_bool_t activated_filter_added;
 } Fixture;
 
 /* this is a macro so it gets the right line number */
@@ -94,6 +100,21 @@ do { \
   g_assert_cmpint (dbus_message_get_reply_serial (m), !=, 0); \
 } while (0)
 
+#define assert_error_reply(m, sender, destination, error_name) \
+do { \
+  g_assert_cmpstr (dbus_message_type_to_string (dbus_message_get_type (m)), \
+      ==, dbus_message_type_to_string (DBUS_MESSAGE_TYPE_ERROR)); \
+  g_assert_cmpstr (dbus_message_get_sender (m), ==, sender); \
+  g_assert_cmpstr (dbus_message_get_destination (m), ==, destination); \
+  g_assert_cmpstr (dbus_message_get_error_name (m), ==, error_name); \
+  g_assert_cmpstr (dbus_message_get_path (m), ==, NULL); \
+  g_assert_cmpstr (dbus_message_get_interface (m), ==, NULL); \
+  g_assert_cmpstr (dbus_message_get_member (m), ==, NULL); \
+  g_assert_cmpstr (dbus_message_get_signature (m), ==, "s"); \
+  g_assert_cmpint (dbus_message_get_serial (m), !=, 0); \
+  g_assert_cmpint (dbus_message_get_reply_serial (m), !=, 0); \
+} while (0)
+
 static DBusHandlerResult
 systemd_filter (DBusConnection *connection,
     DBusMessage *message,
@@ -150,6 +171,27 @@ activated_filter (DBusConnection *connection,
   return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 }
 
+static DBusHandlerResult
+caller_filter (DBusConnection *connection,
+    DBusMessage *message,
+    void *user_data)
+{
+  Fixture *f = user_data;
+
+  if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS,
+        "NameAcquired") ||
+      dbus_message_is_signal (message, DBUS_INTERFACE_DBUS,
+        "NameLost"))
+    {
+      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+    }
+
+  g_assert (f->caller_message == NULL);
+  f->caller_message = dbus_message_ref (message);
+
+  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
 static void
 setup (Fixture *f,
     gconstpointer context G_GNUC_UNUSED)
@@ -203,6 +245,7 @@ test_activation (Fixture *f,
   f->systemd = test_connect_to_bus (f->ctx, f->address);
   if (!dbus_connection_add_filter (f->systemd, systemd_filter, f, NULL))
     g_error ("OOM");
+  f->systemd_filter_added = TRUE;
   f->systemd_name = dbus_bus_get_unique_name (f->systemd);
   take_well_known_name (f, f->systemd, "org.freedesktop.systemd1");
 
@@ -222,6 +265,7 @@ test_activation (Fixture *f,
   if (!dbus_connection_add_filter (f->activated, activated_filter,
         f, NULL))
     g_error ("OOM");
+  f->activated_filter_added = TRUE;
   f->activated_name = dbus_bus_get_unique_name (f->activated);
   take_well_known_name (f, f->activated, "com.example.SystemdActivatable1");
 
@@ -509,6 +553,140 @@ test_uae (Fixture *f,
 }
 
 static void
+test_deny_send (Fixture *f,
+    gconstpointer context)
+{
+  DBusMessage *m;
+
+  if (f->address == NULL)
+    return;
+
+  if (!dbus_connection_add_filter (f->caller, caller_filter, f, NULL))
+    g_error ("OOM");
+
+  f->caller_filter_added = TRUE;
+
+  /* The sender sends a message to an activatable service. */
+  m = dbus_message_new_method_call ("com.example.SendDenied", "/foo",
+      "com.example.bar", "Call");
+  if (m == NULL)
+    g_error ("OOM");
+
+  dbus_connection_send (f->caller, m, NULL);
+  dbus_message_unref (m);
+
+  /* The fake systemd connects to the bus. */
+  f->systemd = test_connect_to_bus (f->ctx, f->address);
+  if (!dbus_connection_add_filter (f->systemd, systemd_filter, f, NULL))
+    g_error ("OOM");
+  f->systemd_filter_added = TRUE;
+  f->systemd_name = dbus_bus_get_unique_name (f->systemd);
+  take_well_known_name (f, f->systemd, "org.freedesktop.systemd1");
+
+  /* It gets its activation request. */
+  while (f->caller_message == NULL && f->systemd_message == NULL)
+    test_main_context_iterate (f->ctx, TRUE);
+
+  g_assert (f->caller_message == NULL);
+  g_assert (f->systemd_message != NULL);
+
+  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");
+  dbus_message_unref (m);
+
+  /* systemd starts the activatable service. */
+  f->activated = test_connect_to_bus (f->ctx, f->address);
+  if (!dbus_connection_add_filter (f->activated, activated_filter,
+        f, NULL))
+    g_error ("OOM");
+  f->activated_filter_added = TRUE;
+  f->activated_name = dbus_bus_get_unique_name (f->activated);
+  take_well_known_name (f, f->activated, "com.example.SendDenied");
+
+  /* We re-do the message matching, and now the message is
+   * forbidden by the receive policy. */
+  while (f->activated_message == NULL && f->caller_message == NULL)
+    test_main_context_iterate (f->ctx, TRUE);
+
+  g_assert (f->activated_message == NULL);
+
+  m = f->caller_message;
+  f->caller_message = NULL;
+  assert_error_reply (m, DBUS_SERVICE_DBUS, f->caller_name,
+      DBUS_ERROR_ACCESS_DENIED);
+  dbus_message_unref (m);
+}
+
+static void
+test_deny_receive (Fixture *f,
+    gconstpointer context)
+{
+  DBusMessage *m;
+
+  if (f->address == NULL)
+    return;
+
+  if (!dbus_connection_add_filter (f->caller, caller_filter, f, NULL))
+    g_error ("OOM");
+
+  f->caller_filter_added = TRUE;
+
+  /* The sender sends a message to an activatable service. */
+  m = dbus_message_new_method_call ("com.example.ReceiveDenied", "/foo",
+      "com.example.ReceiveDenied", "Call");
+  if (m == NULL)
+    g_error ("OOM");
+
+  dbus_connection_send (f->caller, m, NULL);
+  dbus_message_unref (m);
+
+  /* The fake systemd connects to the bus. */
+  f->systemd = test_connect_to_bus (f->ctx, f->address);
+  if (!dbus_connection_add_filter (f->systemd, systemd_filter, f, NULL))
+    g_error ("OOM");
+  f->systemd_filter_added = TRUE;
+  f->systemd_name = dbus_bus_get_unique_name (f->systemd);
+  take_well_known_name (f, f->systemd, "org.freedesktop.systemd1");
+
+  /* It gets its activation request. */
+  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");
+  dbus_message_unref (m);
+
+  /* systemd starts the activatable service. */
+  f->activated = test_connect_to_bus (f->ctx, f->address);
+  if (!dbus_connection_add_filter (f->activated, activated_filter,
+        f, NULL))
+    g_error ("OOM");
+  f->activated_filter_added = TRUE;
+  f->activated_name = dbus_bus_get_unique_name (f->activated);
+  take_well_known_name (f, f->activated, "com.example.ReceiveDenied");
+
+  /* We re-do the message matching, and now the message is
+   * forbidden by the receive policy. */
+  while (f->caller_message == NULL)
+    test_main_context_iterate (f->ctx, TRUE);
+
+  m = f->caller_message;
+  f->caller_message = NULL;
+  assert_error_reply (m, DBUS_SERVICE_DBUS, f->caller_name,
+      DBUS_ERROR_ACCESS_DENIED);
+  dbus_message_unref (m);
+
+  /* The activated service never even saw it. */
+  g_assert (f->activated_message == NULL);
+}
+
+static void
 teardown (Fixture *f,
     gconstpointer context G_GNUC_UNUSED)
 {
@@ -517,6 +695,9 @@ teardown (Fixture *f,
 
   if (f->caller != NULL)
     {
+      if (f->caller_filter_added)
+        dbus_connection_remove_filter (f->caller, caller_filter, f);
+
       dbus_connection_close (f->caller);
       dbus_connection_unref (f->caller);
       f->caller = NULL;
@@ -524,7 +705,9 @@ teardown (Fixture *f,
 
   if (f->systemd != NULL)
     {
-      dbus_connection_remove_filter (f->systemd, systemd_filter, f);
+      if (f->systemd_filter_added)
+        dbus_connection_remove_filter (f->systemd, systemd_filter, f);
+
       dbus_connection_close (f->systemd);
       dbus_connection_unref (f->systemd);
       f->systemd = NULL;
@@ -532,7 +715,9 @@ teardown (Fixture *f,
 
   if (f->activated != NULL)
     {
-      dbus_connection_remove_filter (f->activated, activated_filter, f);
+      if (f->activated_filter_added)
+        dbus_connection_remove_filter (f->activated, activated_filter, f);
+
       dbus_connection_close (f->activated);
       dbus_connection_unref (f->activated);
       f->activated = NULL;
@@ -554,6 +739,10 @@ main (int argc,
       setup, test_activation, teardown);
   g_test_add ("/sd-activation/uae", Fixture, NULL,
       setup, test_uae, teardown);
+  g_test_add ("/sd-activation/deny-send", Fixture, NULL,
+      setup, test_deny_send, teardown);
+  g_test_add ("/sd-activation/deny-receive", Fixture, NULL,
+      setup, test_deny_receive, teardown);
 
   return g_test_run ();
 }