dbus-daemon: add send_destination_prefix support 68/194868/3 accepted/tizen/unified/20190110.060340 submit/tizen/20190109.021130
authorAdrian Szyndela <adrian.s@samsung.com>
Wed, 28 Nov 2018 14:15:16 +0000 (15:15 +0100)
committerHyotaek Shim <hyotaek.shim@samsung.com>
Wed, 9 Jan 2019 02:10:08 +0000 (02:10 +0000)
Change-Id: Iaa1eff400c045ec46465f248e8460c97bb183e5b

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

index cb37c7b..00005cc 100644 (file)
@@ -1180,6 +1180,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 *receive_interface;
@@ -1207,6 +1208,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,
                           "receive_interface", &receive_interface,
@@ -1227,7 +1229,8 @@ append_rule_from_element (BusConfigParser   *parser,
                           NULL))
     return FALSE;
 
-  if (!(send_interface || send_member || send_error || send_destination ||
+  if (!(send_interface || send_member || send_error ||
+        send_destination || send_destination_prefix ||
         send_type || send_path ||
         receive_interface || receive_member || receive_error || receive_sender ||
         receive_type || receive_path || eavesdrop ||
@@ -1281,7 +1284,8 @@ append_rule_from_element (BusConfigParser   *parser,
    *     interface + member
    *     error
    * 
-   *   base send_ can combine with send_destination, send_path, send_type, send_requested_reply
+   *   base send_ can combine with send_destination, send_destination_prefix, send_path, send_type, send_requested_reply
+   *   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
@@ -1318,7 +1322,8 @@ append_rule_from_element (BusConfigParser   *parser,
                       user ||
                       group)) ||
 
-      (send_destination && (receive_interface ||
+      (send_destination && (send_destination_prefix ||
+                            receive_interface ||
                             receive_member ||
                             receive_error ||
                             receive_sender ||
@@ -1327,6 +1332,15 @@ append_rule_from_element (BusConfigParser   *parser,
                             user ||
                             group)) ||
 
+      (send_destination_prefix && (receive_interface ||
+                                   receive_member ||
+                                   receive_error ||
+                                   receive_sender ||
+                                   receive_requested_reply ||
+                                   own || own_prefix ||
+                                   user ||
+                                   group)) ||
+
       (send_type && (receive_interface ||
                      receive_member ||
                      receive_error ||
@@ -1395,7 +1409,7 @@ append_rule_from_element (BusConfigParser   *parser,
    */
 #define IS_WILDCARD(str) ((str) && ((str)[0]) == '*' && ((str)[1]) == '\0')
 
-  if (send_interface || send_member || send_error || send_destination ||
+  if (send_interface || send_member || send_error || send_destination || send_destination_prefix ||
       send_path || send_type || send_requested_reply)
     {
       int message_type;
@@ -1464,7 +1478,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_prefix = 0;
+        }
+      else if (send_destination_prefix)
+        {
+          rule->d.send.destination = _dbus_strdup (send_destination_prefix);
+          rule->d.send.destination_prefix = 1;
+        }
       if (send_path && rule->d.send.path == NULL)
         goto nomem;
       if (send_interface && rule->d.send.interface == NULL)
@@ -1473,7 +1496,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 (receive_interface || receive_member || receive_error || receive_sender ||
index b4a2995..aafc520 100644 (file)
@@ -1458,6 +1458,33 @@ bus_connection_get_n_match_rules (DBusConnection *connection)
   return d->n_match_rules;
 }
 
+dbus_bool_t
+bus_connection_is_service_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 46e883e..6c6fca8 100644 (file)
@@ -98,6 +98,9 @@ dbus_bool_t         bus_connection_replace_deferred_message (DBusConnection *con
 void                bus_connection_dispatch_deferred        (DBusConnection *connection);
 void                bus_connection_clear_deferred_messages  (DBusConnection *connection);
 
+/* called by policy.c */
+dbus_bool_t bus_connection_is_service_owner_by_prefix (DBusConnection *connection,
+                                                       const char *name_prefix);
 
 /* called by signals.c */
 dbus_bool_t bus_connection_add_match_rule      (DBusConnection *connection,
index 3d4f547..1990621 100644 (file)
@@ -1003,46 +1003,85 @@ bus_client_policy_check_can_send (DBusConnection      *sender,
       
       if (rule->d.send.destination != NULL)
         {
-          /* receiver can be NULL for messages that are sent to the
-           * message bus itself, we check the strings in that case as
-           * built-in services don't have a DBusConnection but messages
-           * to them have a destination service name.
-           *
-           * Similarly, receiver can be NULL when we're deciding whether
-           * activation should be allowed; we make the authorization decision
-           * on the assumption that the activated service will have the
-           * requested name and no others.
-           */
-          if (receiver == NULL)
+          if (!rule->d.send.destination_prefix)
             {
-              if (!dbus_message_has_destination (message,
-                                                 rule->d.send.destination))
+              /* receiver can be NULL for messages that are sent to the
+               * message bus itself, we check the strings in that case as
+               * built-in services don't have a DBusConnection but messages
+               * to them have a destination service name.
+               *
+               * Similarly, receiver can be NULL when we're deciding whether
+               * activation should be allowed; we make the authorization decision
+               * on the assumption that the activated service will have the
+               * requested name and no others.
+               */
+              if (receiver == NULL)
                 {
-                  _dbus_verbose ("  (policy) skipping rule because message dest is not %s\n",
-                                 rule->d.send.destination);
-                  continue;
+                  if (!dbus_message_has_destination (message,
+                                                     rule->d.send.destination))
+                    {
+                      _dbus_verbose ("  (policy) skipping rule because message dest is not %s\n",
+                                     rule->d.send.destination);
+                      continue;
+                    }
+                }
+              else
+                {
+                  DBusString str;
+                  BusService *service;
+
+                  _dbus_string_init_const (&str, rule->d.send.destination);
+
+                  service = bus_registry_lookup (registry, &str);
+                  if (service == NULL)
+                    {
+                      _dbus_verbose ("  (policy) skipping rule because dest %s doesn't exist\n",
+                                     rule->d.send.destination);
+                      continue;
+                    }
+
+                  if (!bus_service_has_owner (service, receiver))
+                    {
+                      _dbus_verbose ("  (policy) skipping rule because dest %s isn't owned by receiver\n",
+                                     rule->d.send.destination);
+                      continue;
+                    }
                 }
             }
-          else
+          else if (rule->d.send.destination_prefix)
             {
-              DBusString str;
-              BusService *service;
-              
-              _dbus_string_init_const (&str, rule->d.send.destination);
-              
-              service = bus_registry_lookup (registry, &str);
-              if (service == NULL)
+              /* receiver can be NULL - the same as in !send.destination_prefix */
+              if (receiver == NULL)
                 {
-                  _dbus_verbose ("  (policy) skipping rule because dest %s doesn't exist\n",
-                                 rule->d.send.destination);
-                  continue;
+                  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;
+                    }
                 }
-
-              if (!bus_service_has_owner (service, receiver))
+              else
                 {
-                  _dbus_verbose ("  (policy) skipping rule because dest %s isn't owned by receiver\n",
-                                 rule->d.send.destination);
-                  continue;
+                  if (!bus_connection_is_service_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;
+                    }
                 }
             }
         }
@@ -1365,15 +1404,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;
         }
 
index 1f23431..d80c775 100644 (file)
@@ -75,6 +75,7 @@ struct BusPolicyRule
       unsigned int eavesdrop : 1;
       unsigned int requested_reply : 1;
       unsigned int log : 1;
+      unsigned int destination_prefix : 1;
     } send;
 
     struct
index 98d9f2b..7a7bd8f 100644 (file)
@@ -2214,6 +2214,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.
  *
index adf709b..388e762 100644 (file)
@@ -319,6 +319,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