From 7309aae6b0fa8019d6d3362e156eea46a7e1390d Mon Sep 17 00:00:00 2001
From: Simo Sorce <simo@redhat.com>
Date: Wed, 20 Jan 2016 10:33:39 -0500
Subject: [PATCH 06/15] ConfDB: Add helper function to get "subsections"

The secrets database will have "subsections", ie sections that are in the
"secrets" namespace and look like this: [secrets/<path>]

This function allows to source any section under secrets/ or under any
arbitrary sub-path.

Related:
https://fedorahosted.org/sssd/ticket/2913
---
 src/confdb/confdb.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/confdb/confdb.h | 26 +++++++++++++++
 2 files changed, 118 insertions(+)

diff --git a/src/confdb/confdb.c b/src/confdb/confdb.c
index d409344890c869aa3e7b2dbb49c0f51cd3a20adc..03adbe593b42f556b560df77d410f80460200a67 100644
--- a/src/confdb/confdb.c
+++ b/src/confdb/confdb.c
@@ -1531,3 +1531,95 @@ done:
     talloc_free(tmp_ctx);
     return ret;
 }
+
+int confdb_get_sub_sections(TALLOC_CTX *mem_ctx,
+                            struct confdb_ctx *cdb,
+                            const char *section,
+                            char ***sections,
+                            int *num_sections)
+{
+    TALLOC_CTX *tmp_ctx = NULL;
+    char *secdn;
+    struct ldb_dn *base = NULL;
+    struct ldb_result *res = NULL;
+    static const char *attrs[] = {"cn", NULL};
+    char **names;
+    int base_comp_num;
+    int num;
+    int i;
+    int ret;
+
+    tmp_ctx = talloc_new(mem_ctx);
+    if (tmp_ctx == NULL) {
+        return ENOMEM;
+    }
+
+    ret = parse_section(tmp_ctx, section, &secdn, NULL);
+    if (ret != EOK) {
+        goto done;
+    }
+
+    base = ldb_dn_new(tmp_ctx, cdb->ldb, secdn);
+    if (base == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    base_comp_num = ldb_dn_get_comp_num(base);
+
+    ret = ldb_search(cdb->ldb, tmp_ctx, &res, base, LDB_SCOPE_SUBTREE,
+                     attrs, NULL);
+    if (ret != LDB_SUCCESS) {
+        ret = EIO;
+        goto done;
+    }
+
+    names = talloc_zero_array(tmp_ctx, char *, res->count + 1);
+    if (names == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    for (num = 0, i = 0; i < res->count; i++) {
+        const struct ldb_val *val;
+        char *name;
+        int n;
+        int j;
+
+        n = ldb_dn_get_comp_num(res->msgs[i]->dn);
+        if (n == base_comp_num) continue;
+
+        name = NULL;
+        for (j = n - base_comp_num - 1; j >= 0; j--) {
+            val = ldb_dn_get_component_val(res->msgs[i]->dn, j);
+            if (name == NULL) {
+                name = talloc_strndup(names,
+                                      (const char *)val->data, val->length);
+            } else {
+                name = talloc_asprintf(names, "%s/%.*s", name,
+                                       (int)val->length,
+                                       (const char *)val->data);
+            }
+            if (name == NULL) {
+                ret = ENOMEM;
+                goto done;
+            }
+        }
+
+        names[num] = name;
+        if (names[num] == NULL) {
+            ret = ENOMEM;
+            goto done;
+        }
+
+        num++;
+    }
+
+    *sections = talloc_steal(mem_ctx, names);
+    *num_sections = num;
+    ret = EOK;
+
+done:
+    talloc_free(tmp_ctx);
+    return ret;
+}
diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
index e6789c8665cf677712d8e7fb72b6f0a41bca80b1..778d2ce81c3d08ae2be3893c3afafef28f057f85 100644
--- a/src/confdb/confdb.h
+++ b/src/confdb/confdb.h
@@ -559,6 +559,32 @@ int confdb_set_string(struct confdb_ctx *cdb,
 int confdb_get_string_as_list(struct confdb_ctx *cdb, TALLOC_CTX *ctx,
                               const char *section, const char *attribute,
                               char ***result);
+
+/**
+ * @brief Convenience function to retrieve a list of subsections given a
+ * configuration section name
+ *
+ * @param[in] memctx The parent memory context for the returned list
+ * @param[in] cdb The connection object to the confdb
+ * @param[in] section The ConfDB section to look for.
+ *                    All sections should start with 'config/'.
+ *                    Subsections are separated by slashes.
+ * @param[out] sections Names of the subsections realtive to the section
+ *                      requested. If "a/b" is requested then "c/d" is
+ *                      returned for the section named [a/b/c/d]
+ * @param[out] num_sections Number of section names returned
+ *
+ * @return 0 - Successfully retrieved the entry (or used the default)
+ * @return ENOMEM - There was insufficient memory to complete the operation
+ * @return EINVAL - The section could not be parsed.
+ * @return ENOENT - No section was found.
+ * @return EIO - An I/O error occurred while communicating with the ConfDB
+ */
+int confdb_get_sub_sections(TALLOC_CTX *mem_ctx,
+                            struct confdb_ctx *cdb,
+                            const char *section,
+                            char ***sections,
+                            int *num_sections);
 /**
  * @}
  */
-- 
2.5.5

