From be552bf54a91e27c5d04a1e56bc1c3d3ded62d30 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Thu, 29 Jan 2015 15:29:26 +0100
Subject: [PATCH 2/8] sbus: add sbus_opath_decompose[_exact]

This function decomposes object path into array of strings. The
"_exact" version expects a certain number of parts otherwise an
error is thrown.
---
 src/sbus/sssd_dbus.h               |  14 ++++
 src/sbus/sssd_dbus_interface.c     |  93 +++++++++++++++++++++++++++
 src/tests/cmocka/test_sbus_opath.c | 128 +++++++++++++++++++++++++++++++++++++
 src/util/util_errors.c             |   1 +
 src/util/util_errors.h             |   1 +
 5 files changed, 237 insertions(+)

diff --git a/src/sbus/sssd_dbus.h b/src/sbus/sssd_dbus.h
index 6d2d5897ab5f50b1c7d48393be60a28e1333837d..61c18ae28f4617239ed0e941f6cf5dd9fe0b24db 100644
--- a/src/sbus/sssd_dbus.h
+++ b/src/sbus/sssd_dbus.h
@@ -196,6 +196,20 @@ _sbus_opath_compose(TALLOC_CTX *mem_ctx,
 #define sbus_opath_compose(mem_ctx, base, ...) \
     _sbus_opath_compose(mem_ctx, base, ##__VA_ARGS__, NULL)
 
+errno_t
+sbus_opath_decompose(TALLOC_CTX *mem_ctx,
+                     const char *object_path,
+                     const char *prefix,
+                     char ***_components,
+                     size_t *_len);
+
+errno_t
+sbus_opath_decompose_exact(TALLOC_CTX *mem_ctx,
+                           const char *object_path,
+                           const char *prefix,
+                           size_t expected,
+                           char ***_components);
+
 const char *
 sbus_opath_strip_prefix(const char *object_path,
                         const char *prefix);
diff --git a/src/sbus/sssd_dbus_interface.c b/src/sbus/sssd_dbus_interface.c
index d4ddce0acc710dba0da2a6b0a036c282fa208e3d..53f393e5cfba29302fb5915bdec23035ae0fb8d0 100644
--- a/src/sbus/sssd_dbus_interface.c
+++ b/src/sbus/sssd_dbus_interface.c
@@ -354,6 +354,99 @@ fail:
     return NULL;
 }
 
+errno_t
+sbus_opath_decompose(TALLOC_CTX *mem_ctx,
+                     const char *object_path,
+                     const char *prefix,
+                     char ***_components,
+                     size_t *_len)
+{
+    TALLOC_CTX *tmp_ctx;
+    const char *path;
+    char **decomposed;
+    char **unescaped;
+    errno_t ret;
+    int len;
+    int i;
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        return ENOMEM;
+    }
+
+    /* Strip prefix from the path. */
+    if (prefix != NULL) {
+        path = sbus_opath_strip_prefix(object_path, prefix);
+        if (path == NULL) {
+            ret = ERR_SBUS_INVALID_PATH;
+            goto done;
+        }
+    } else {
+        path = object_path;
+    }
+
+    /* Split the string using / as delimiter. */
+    split_on_separator(tmp_ctx, path, '/', true, true, &decomposed, &len);
+
+    /* Unescape parts. */
+    unescaped = talloc_zero_array(tmp_ctx, char *, len + 1);
+    if (unescaped == NULL) {
+        ret = ENOMEM;
+        goto done;
+    }
+
+    for (i = 0; i < len; i++) {
+        unescaped[i] = sbus_opath_unescape_part(unescaped, decomposed[i]);
+        if (unescaped[i] == NULL) {
+            ret = ENOMEM;
+            goto done;
+        }
+    }
+
+    if (_components != NULL) {
+        *_components = talloc_steal(mem_ctx, unescaped);
+    }
+
+    if (_len != NULL) {
+        *_len = len;
+    }
+
+    ret = EOK;
+
+done:
+    talloc_free(tmp_ctx);
+    return ret;
+}
+
+errno_t
+sbus_opath_decompose_exact(TALLOC_CTX *mem_ctx,
+                           const char *object_path,
+                           const char *prefix,
+                           size_t expected,
+                           char ***_components)
+{
+    char **components;
+    size_t len;
+    errno_t ret;
+
+    ret = sbus_opath_decompose(mem_ctx, object_path, prefix,
+                               &components, &len);
+    if (ret != EOK) {
+        return ret;
+    }
+
+    if (len != expected) {
+        talloc_free(components);
+        return ERR_SBUS_INVALID_PATH;
+    }
+
+    if (_components != NULL) {
+        *_components = components;
+    }
+
+    return EOK;
+}
+
 const char *
 sbus_opath_strip_prefix(const char *object_path,
                         const char *prefix)
diff --git a/src/tests/cmocka/test_sbus_opath.c b/src/tests/cmocka/test_sbus_opath.c
index 4c57c56e7ebbcac3665c466e1f3d947f7bec92c4..e38eaf1972b55f01d712584b67c731ac0031736d 100644
--- a/src/tests/cmocka/test_sbus_opath.c
+++ b/src/tests/cmocka/test_sbus_opath.c
@@ -121,6 +121,127 @@ void test_sbus_opath_compose_escape(void **state)
     talloc_free(path);
 }
 
+static void check_opath_components(char **input,
+                                   const char **expected)
+{
+    int i;
+
+    assert_non_null(input);
+    assert_non_null(expected);
+
+    for (i = 0; input[i] != NULL; i++) {
+        assert_non_null(input[i]);
+        assert_non_null(expected[i]);
+        assert_string_equal(input[i], expected[i]);
+    }
+
+    assert_null(input[i]);
+    assert_null(expected[i]);
+}
+
+static void check_opath_components_and_length(char **input,
+                                              size_t input_len,
+                                              const char **expected,
+                                              size_t expected_len)
+{
+    assert_true(input_len == expected_len);
+    check_opath_components(input, expected);
+}
+
+void test_sbus_opath_decompose_noprefix(void **state)
+{
+    const char *path = "/object/path/parts";
+    const char *expected[] = {"object", "path", "parts", NULL};
+    size_t expected_len = sizeof(expected) / sizeof(char *) - 1;
+    char **components;
+    size_t len;
+    errno_t ret;
+
+    ret = sbus_opath_decompose(NULL, path, NULL, &components, &len);
+    assert_int_equal(ret, EOK);
+    check_opath_components_and_length(components, len, expected, expected_len);
+    talloc_free(components);
+}
+
+void test_sbus_opath_decompose_prefix(void **state)
+{
+    const char *path = "/object/path/parts";
+    const char *expected[] = {"parts", NULL};
+    size_t expected_len = sizeof(expected) / sizeof(char *) - 1;
+    char **components;
+    size_t len;
+    errno_t ret;
+
+    ret = sbus_opath_decompose(NULL, path, "/object/path", &components, &len);
+    assert_int_equal(ret, EOK);
+    check_opath_components_and_length(components, len, expected, expected_len);
+    talloc_free(components);
+}
+
+void test_sbus_opath_decompose_prefix_slash(void **state)
+{
+    const char *path = "/object/path/parts";
+    const char *expected[] = {"parts", NULL};
+    size_t expected_len = sizeof(expected) / sizeof(char *) - 1;
+    char **components;
+    size_t len;
+    errno_t ret;
+
+    ret = sbus_opath_decompose(NULL, path, "/object/path/", &components, &len);
+    assert_int_equal(ret, EOK);
+    check_opath_components_and_length(components, len, expected, expected_len);
+    talloc_free(components);
+}
+
+void test_sbus_opath_decompose_wrong_prefix(void **state)
+{
+    const char *path = "/object/path/parts";
+    char **components;
+    size_t len;
+    errno_t ret;
+
+    ret = sbus_opath_decompose(NULL, path, "/wrong/prefix", &components, &len);
+    assert_int_equal(ret, ERR_SBUS_INVALID_PATH);
+}
+
+void test_sbus_opath_decompose_escaped(void **state)
+{
+    const char *path = "/object/redhat_2ecom";
+    const char *expected[] = {"object", "redhat.com", NULL};
+    size_t expected_len = sizeof(expected) / sizeof(char *) - 1;
+    char **components;
+    size_t len;
+    errno_t ret;
+
+    ret = sbus_opath_decompose(NULL, path, NULL, &components, &len);
+    assert_int_equal(ret, EOK);
+    check_opath_components_and_length(components, len, expected, expected_len);
+    talloc_free(components);
+}
+
+void test_sbus_opath_decompose_exact_correct(void **state)
+{
+    const char *path = "/object/path/parts";
+    const char *expected[] = {"object", "path", "parts", NULL};
+    char **components;
+    errno_t ret;
+
+    ret = sbus_opath_decompose_exact(NULL, path, NULL, 3, &components);
+    assert_int_equal(ret, EOK);
+    check_opath_components(components, expected);
+    talloc_free(components);
+}
+
+void test_sbus_opath_decompose_exact_wrong(void **state)
+{
+    const char *path = "/object/path/parts";
+    char **components;
+    errno_t ret;
+
+    ret = sbus_opath_decompose_exact(NULL, path, NULL, 2, &components);
+    assert_int_equal(ret, ERR_SBUS_INVALID_PATH);
+}
+
 void test_sbus_opath_get_object_name(void **state)
 {
     const char *path = BASE_PATH "/redhat_2ecom";
@@ -158,6 +279,13 @@ int main(int argc, const char *argv[])
         cmocka_unit_test(test_sbus_opath_escape_unescape),
         cmocka_unit_test(test_sbus_opath_compose),
         cmocka_unit_test(test_sbus_opath_compose_escape),
+        cmocka_unit_test(test_sbus_opath_decompose_noprefix),
+        cmocka_unit_test(test_sbus_opath_decompose_prefix),
+        cmocka_unit_test(test_sbus_opath_decompose_prefix_slash),
+        cmocka_unit_test(test_sbus_opath_decompose_wrong_prefix),
+        cmocka_unit_test(test_sbus_opath_decompose_escaped),
+        cmocka_unit_test(test_sbus_opath_decompose_exact_correct),
+        cmocka_unit_test(test_sbus_opath_decompose_exact_wrong),
         cmocka_unit_test(test_sbus_opath_get_object_name)
     };
 
diff --git a/src/util/util_errors.c b/src/util/util_errors.c
index ac08f6277def4ada16ec61e7843ac482bc1b1e7c..3c99681ce81856e8f90d16afc7e8be58ee2383ae 100644
--- a/src/util/util_errors.c
+++ b/src/util/util_errors.c
@@ -62,6 +62,7 @@ struct err_string error_to_str[] = {
     { "Malformed extra attribute" }, /* ERR_INVALID_EXTRA_ATTR */
     { "Cannot get bus message sender" }, /* ERR_SBUS_GET_SENDER_ERROR */
     { "Bus message has no sender" }, /* ERR_SBUS_NO_SENDER */
+    { "Invalid SBUS path provided." }, /* ERR_SBUS_INVALID_PATH */
     { "User/Group SIDs not found" }, /* ERR_NO_SIDS */
     { "Bus method not supported" }, /* ERR_SBUS_NOSUP */
     { "Cannot connect to system bus" }, /* ERR_NO_SYSBUS */
diff --git a/src/util/util_errors.h b/src/util/util_errors.h
index c03274ce24275ffb6b3493d6eb74e072d17a61a0..1e28c3a808376ca1a3affc4b5453f1d4031fda32 100644
--- a/src/util/util_errors.h
+++ b/src/util/util_errors.h
@@ -84,6 +84,7 @@ enum sssd_errors {
     ERR_INVALID_EXTRA_ATTR,
     ERR_SBUS_GET_SENDER_ERROR,
     ERR_SBUS_NO_SENDER,
+    ERR_SBUS_INVALID_PATH,
     ERR_NO_SIDS,
     ERR_SBUS_NOSUP,
     ERR_NO_SYSBUS,
-- 
2.1.0

