]> git.ipfire.org Git - thirdparty/dbus.git/commitdiff
dbus-daemon: add send_destination_prefix support
authorAdrian Szyndela <adrian.s@samsung.com>
Wed, 28 Nov 2018 14:15:16 +0000 (15:15 +0100)
committerAdrian Szyndela <adrian.s@samsung.com>
Fri, 26 Apr 2019 11:29:42 +0000 (13:29 +0200)
This extends dbus-daemon with support for send_destination_prefix
attribute in XML policies.

It allows having policy rules for sending to bus names generated
within namespaces defined by a prefix. The similar behaviour can be
emulated by owning an additional name, not used for addressing messages,
as described in
https://lists.freedesktop.org/archives/dbus/2017-May/017188.html
However, introducing send_destination_prefix creates possibility
of communicating intentions in a more direct way, which is easier
to understand.

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

bus/config-parser.c
bus/connection.c
bus/connection.h
bus/policy.c
bus/policy.h

index 4e62c342e5cf4f9e333aa9524b901414823d4b81..a47b8a583a0fe9d19329e1b1a3fd5ab81d4ed64b 100644 (file)
@@ -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)
index 3af980d0341ff8e4e6118aea9b50745730f230db..5943841d8db6ac2c955fec5db7b61b073fd1eb13 100644 (file)
@@ -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)
index 949a2231f194bec3b62541cf33aed02858ae1751..912638c0edb574319dc51f16e55b2c149c2e5454 100644 (file)
@@ -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);
index 11d21bf01467f3882dd886b51072314ed6bfb042..feb1156e887b7c8c9649501c81bce2dff4912a09 100644 (file)
@@ -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)
         {
index 308eaf862641a8e03149b93e3f8708403a5b0df5..df59d09043285f7d1f71cbaa452bd8279e470cf6 100644 (file)
@@ -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