From 2a14d7d8fae7c31bf96c26dd084b4be2cb72ad7c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Thu, 11 Dec 2014 11:01:57 +0100
Subject: [PATCH 3/9] sbus: use 'path/*' to represent a D-Bus fallback

Use 'path/*' instead of 'path*' since it better describes what
we are actually doing i.e. registering a message handler for a
subtree.

Although D-Bus fallback will invoke a message handler for both
'path' and 'path/subtree' object paths it does not make usually
sence to support the same interfaces for both parent and it
children.

This commit also renames related functions to better describe
what are they doing.

Note: the tilda in comments is used to suppress -Wcomment warning

Preparation for:
https://fedorahosted.org/sssd/ticket/2339
---
 src/responder/ifp/ifp_components.h |  2 +-
 src/responder/ifp/ifp_domains.h    |  2 +-
 src/sbus/sssd_dbus_interface.c     | 92 +++++++++++++++++++++++---------------
 3 files changed, 58 insertions(+), 38 deletions(-)

diff --git a/src/responder/ifp/ifp_components.h b/src/responder/ifp/ifp_components.h
index 49f1294cd32bdd6e6a2cbbf2937e1e66e0ad4dc8..6c6300442762c083e53b5be524d706d0dcf508d4 100644
--- a/src/responder/ifp/ifp_components.h
+++ b/src/responder/ifp/ifp_components.h
@@ -25,7 +25,7 @@
 #include "responder/ifp/ifp_private.h"
 
 #define INFOPIPE_COMPONENT_PATH_PFX "/org/freedesktop/sssd/infopipe/Components"
-#define INFOPIPE_COMPONENT_PATH INFOPIPE_COMPONENT_PATH_PFX "*"
+#define INFOPIPE_COMPONENT_PATH INFOPIPE_COMPONENT_PATH_PFX "/*"
 
 #define INFOPIPE_BACKEND_PATH INFOPIPE_COMPONENT_PATH_PFX "/Backends*"
 
diff --git a/src/responder/ifp/ifp_domains.h b/src/responder/ifp/ifp_domains.h
index d6ef1a04d10ee69ea620fb638c8ee358d3fe21f5..d6ed6c73deb47a78775424afa28915b38d358777 100644
--- a/src/responder/ifp/ifp_domains.h
+++ b/src/responder/ifp/ifp_domains.h
@@ -26,7 +26,7 @@
 #include "responder/ifp/ifp_private.h"
 
 #define INFOPIPE_DOMAIN_PATH_PFX "/org/freedesktop/sssd/infopipe/Domains"
-#define INFOPIPE_DOMAIN_PATH     INFOPIPE_DOMAIN_PATH_PFX"*"
+#define INFOPIPE_DOMAIN_PATH     INFOPIPE_DOMAIN_PATH_PFX"/*"
 
 /* org.freedesktop.sssd.infopipe */
 
diff --git a/src/sbus/sssd_dbus_interface.c b/src/sbus/sssd_dbus_interface.c
index fd11c2c2d2214ecaff61ee44fffc710c2a54d439..cd41c4f29f700d010836a45c73092a0eb16ec9f2 100644
--- a/src/sbus/sssd_dbus_interface.c
+++ b/src/sbus/sssd_dbus_interface.c
@@ -28,21 +28,6 @@
 DBusObjectPathVTable dbus_object_path_vtable =
     { NULL, sbus_message_handler, NULL, NULL, NULL, NULL };
 
-static char *sbus_iface_get_reg_path(TALLOC_CTX *mem_ctx,
-                                     const char *path,
-                                     bool fallback)
-{
-    char *reg_path;
-
-    reg_path = talloc_strdup(mem_ctx, path);
-    if (reg_path == NULL) return NULL;
-
-    if (fallback) {
-        reg_path[strlen(path)-1] = '\0';
-    }
-    return reg_path;
-}
-
 static bool path_in_interface_list(struct sbus_interface_p *list,
                                    const char *path)
 {
@@ -74,38 +59,73 @@ void sbus_unreg_object_paths(struct sbus_connection *conn)
     }
 }
 
-static bool sbus_fb_path_has_prefix(const char *path, const char *prefix)
+/**
+ * Object paths that represent all objects under the path:
+ * /org/object/path/~* (without tilda)
+ */
+static bool sbus_opath_is_subtree(const char *path)
 {
-    /* strlen-1 because we don't want to match the trailing '*' */
-    if (strncmp(path, prefix, strlen(prefix)-1) == 0) {
-        return true;
+    size_t len;
+
+    len = strlen(path);
+
+    if (len < 2) {
+        return false;
+    }
+
+    return path[len - 2] == '/' && path[len - 1] == '*';
+}
+
+static bool sbus_opath_match_tree(const char *object_path,
+                                  const char *tree_path)
+{
+    if (object_path == NULL || tree_path == NULL || tree_path[0] == '\0') {
+        return false;
+    };
+
+    /* first check if tree is a base path or a subtree path */
+    if (!sbus_opath_is_subtree(tree_path)) {
+        return strcmp(object_path, tree_path) == 0;
     }
 
-    return false;
+    /* Compare without the asterisk, which is the last character.
+     * Slash, that has to be present before the asterisk, will ensure that only
+     * subtree object path matches. */
+    return strncmp(object_path, tree_path, strlen(tree_path) - 1) == 0;
 }
 
-static bool sbus_path_has_fallback(const char *path)
+/**
+ * If the path represents a subtree object path, this function will
+ * remove /~* from the end.
+ */
+static char *sbus_opath_get_base_path(TALLOC_CTX *mem_ctx,
+                                      const char *object_path)
 {
-    char *wildcard;
-
-    wildcard = strrchr(path, '*');
-    if (wildcard != NULL) {
-        /* This path was registered as fallback */
-        if (*(wildcard + 1) != '\0') {
-            /* Wildcard is only allowed as the last character in the path */
-            return false;
-        }
-        return true;
+    char *tree_path;
+    size_t len;
+
+    tree_path = talloc_strdup(mem_ctx, object_path);
+    if (tree_path == NULL) {
+        return NULL;
     }
 
-    return false;
+    if (!sbus_opath_is_subtree(tree_path)) {
+        return tree_path;
+    }
+
+    /* replace / only if it is not a root path (only slash) */
+    len = strlen(tree_path);
+    tree_path[len - 1] = '\0';
+    tree_path[len - 2] = len - 2 != 0 ? '\0' : '/';
+
+    return tree_path;
 }
 
 bool sbus_iface_handles_path(struct sbus_interface_p *intf_p,
                                     const char *path)
 {
-    if (sbus_path_has_fallback(intf_p->intf->path)) {
-        return sbus_fb_path_has_prefix(path, intf_p->intf->path);
+    if (sbus_opath_is_subtree(intf_p->intf->path)) {
+        return sbus_opath_match_tree(path, intf_p->intf->path);
     }
 
     return strcmp(path, intf_p->intf->path) == 0;
@@ -158,7 +178,7 @@ int sbus_conn_register_iface(struct sbus_connection *conn,
     }
 
     path = intf->path;
-    fallback = sbus_path_has_fallback(path);
+    fallback = sbus_opath_is_subtree(path);
 
     if (path_in_interface_list(conn->intf_list, path)) {
         DEBUG(SSSDBG_FATAL_FAILURE,
@@ -172,7 +192,7 @@ int sbus_conn_register_iface(struct sbus_connection *conn,
     }
     intf_p->conn = conn;
     intf_p->intf = intf;
-    intf_p->reg_path = sbus_iface_get_reg_path(intf_p, path, fallback);
+    intf_p->reg_path = sbus_opath_get_base_path(intf_p, path);
     if (intf_p->reg_path == NULL) {
         return ENOMEM;
     }
-- 
1.7.11.7

