Blob Blame History Raw
From b86a642a321d3763d997f07c47ec515acbe72cf0 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Tue, 28 Oct 2014 19:40:02 +0100
Subject: [PATCH 57/64] Add parse_attr_list_ex() helper function

Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
---
 Makefile.am                            |   5 +-
 src/responder/common/responder.h       |   2 +
 src/responder/common/responder_utils.c | 151 +++++++++++++++++++++++++++++++++
 src/responder/ifp/ifp_private.h        |   3 +
 src/responder/ifp/ifpsrv_util.c        | 117 +------------------------
 src/tests/cmocka/test_ifp.c            |  51 +++++++++++
 6 files changed, 212 insertions(+), 117 deletions(-)
 create mode 100644 src/responder/common/responder_utils.c

diff --git a/Makefile.am b/Makefile.am
index 61bf5cf957d4024b67f48cf42f5735b5fa368945..ac8ad1566a5c931bf43526e2d29a57a5f8ade1cf 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -409,6 +409,7 @@ SSSD_RESPONDER_OBJ = \
     src/responder/common/responder_dp.c \
     src/responder/common/responder_packet.c \
     src/responder/common/responder_get_domains.c \
+    src/responder/common/responder_utils.c \
     src/monitor/monitor_iface_generated.c \
     src/monitor/monitor_iface_generated.h \
     src/providers/data_provider_iface_generated.c \
@@ -2025,7 +2026,9 @@ ifp_tests_SOURCES = \
     src/tests/cmocka/test_ifp.c \
     src/responder/ifp/ifpsrv_cmd.c \
     src/responder/ifp/ifp_iface_generated.c \
-    src/responder/ifp/ifpsrv_util.c
+    src/responder/ifp/ifpsrv_util.c \
+    src/responder/common/responder_utils.c \
+    $(NULL)
 ifp_tests_CFLAGS = \
     $(AM_CFLAGS)
 ifp_tests_LDADD = \
diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h
index e3c0f226775d279ea8c0f300cc2de54d2f7f9b72..02a215ced435c87ec0439807ab5e575de0d0fe04 100644
--- a/src/responder/common/responder.h
+++ b/src/responder/common/responder.h
@@ -329,4 +329,6 @@ sss_parse_inp_send(TALLOC_CTX *mem_ctx, struct resp_ctx *rctx,
 errno_t sss_parse_inp_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
                            char **_name, char **_domname);
 
+const char **parse_attr_list_ex(TALLOC_CTX *mem_ctx, const char *conf_str,
+                                const char **defaults);
 #endif /* __SSS_RESPONDER_H__ */
diff --git a/src/responder/common/responder_utils.c b/src/responder/common/responder_utils.c
new file mode 100644
index 0000000000000000000000000000000000000000..815b61b3971cfda2eda4efc643ea21c3b035b36d
--- /dev/null
+++ b/src/responder/common/responder_utils.c
@@ -0,0 +1,151 @@
+
+/*
+   SSSD
+
+   Common Responder utility functions
+
+   Copyright (C) Sumit Bose <sbose@redhat.com> 2014
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <talloc.h>
+
+#include "util/util.h"
+
+static inline bool
+attr_in_list(const char **list, size_t nlist, const char *str)
+{
+    size_t i;
+
+    for (i = 0; i < nlist; i++) {
+        if (strcasecmp(list[i], str) == 0) {
+            break;
+        }
+    }
+
+    return (i < nlist) ? true : false;
+}
+
+const char **parse_attr_list_ex(TALLOC_CTX *mem_ctx, const char *conf_str,
+                                const char **defaults)
+{
+    TALLOC_CTX *tmp_ctx;
+    errno_t ret;
+    const char **list = NULL;
+    const char **res = NULL;
+    int list_size;
+    char **conf_list = NULL;
+    int conf_list_size = 0;
+    const char **allow = NULL;
+    const char **deny = NULL;
+    int ai = 0, di = 0, li = 0;
+    int i;
+
+    tmp_ctx = talloc_new(NULL);
+    if (tmp_ctx == NULL) {
+        return NULL;
+    }
+
+    if (conf_str) {
+        ret = split_on_separator(tmp_ctx, conf_str, ',', true, true,
+                                 &conf_list, &conf_list_size);
+        if (ret != EOK) {
+            DEBUG(SSSDBG_OP_FAILURE,
+                  "Cannot parse attribute ACL list  %s: %d\n", conf_str, ret);
+            goto done;
+        }
+
+        allow = talloc_zero_array(tmp_ctx, const char *, conf_list_size);
+        deny = talloc_zero_array(tmp_ctx, const char *, conf_list_size);
+        if (allow == NULL || deny == NULL) {
+            goto done;
+        }
+    }
+
+    for (i = 0; i < conf_list_size; i++) {
+        switch (conf_list[i][0]) {
+            case '+':
+                allow[ai] = conf_list[i] + 1;
+                ai++;
+                continue;
+            case '-':
+                deny[di] = conf_list[i] + 1;
+                di++;
+                continue;
+            default:
+                DEBUG(SSSDBG_CRIT_FAILURE, "ACL values must start with "
+                      "either '+' (allow) or '-' (deny), got '%s'\n",
+                      conf_list[i]);
+                goto done;
+        }
+    }
+
+    /* Assume the output will have to hold defaults and all the configured,
+     * values, resize later
+     */
+    list_size = 0;
+    if (defaults != NULL) {
+        while (defaults[list_size]) {
+            list_size++;
+        }
+    }
+    list_size += conf_list_size;
+
+    list = talloc_zero_array(tmp_ctx, const char *, list_size + 1);
+    if (list == NULL) {
+        goto done;
+    }
+
+    /* Start by copying explicitly allowed attributes */
+    for (i = 0; i < ai; i++) {
+        /* if the attribute is explicitly denied, skip it */
+        if (attr_in_list(deny, di, allow[i])) {
+            continue;
+        }
+
+        list[li] = talloc_strdup(list, allow[i]);
+        if (list[li] == NULL) {
+            goto done;
+        }
+        li++;
+
+        DEBUG(SSSDBG_TRACE_INTERNAL,
+              "Added allowed attr %s to whitelist\n", allow[i]);
+    }
+
+    /* Add defaults */
+    if (defaults != NULL) {
+        for (i = 0; defaults[i]; i++) {
+            /* if the attribute is explicitly denied, skip it */
+            if (attr_in_list(deny, di, defaults[i])) {
+                continue;
+            }
+
+            list[li] = talloc_strdup(list, defaults[i]);
+            if (list[li] == NULL) {
+                goto done;
+            }
+            li++;
+
+            DEBUG(SSSDBG_TRACE_INTERNAL,
+                  "Added default attr %s to whitelist\n", defaults[i]);
+        }
+    }
+
+    res = talloc_steal(mem_ctx, list);
+done:
+    talloc_free(tmp_ctx);
+    return res;
+}
diff --git a/src/responder/ifp/ifp_private.h b/src/responder/ifp/ifp_private.h
index bf2015a9722ff4b4f831cb63cd528881f0f259a8..fb1639c8dfd00f547a666dce67ee7a94c3143618 100644
--- a/src/responder/ifp/ifp_private.h
+++ b/src/responder/ifp/ifp_private.h
@@ -82,5 +82,8 @@ char *_ifp_reply_objpath(TALLOC_CTX *mem_ctx, const char *base,
 errno_t ifp_add_ldb_el_to_dict(DBusMessageIter *iter_dict,
                                struct ldb_message_element *el);
 const char **ifp_parse_attr_list(TALLOC_CTX *mem_ctx, const char *conf_str);
+const char **
+ifp_parse_attr_list_ex(TALLOC_CTX *mem_ctx, const char *conf_str,
+                       const char **defaults);
 bool ifp_attr_allowed(const char *whitelist[], const char *attr);
 #endif /* _IFPSRV_PRIVATE_H_ */
diff --git a/src/responder/ifp/ifpsrv_util.c b/src/responder/ifp/ifpsrv_util.c
index c0ab686e4527a2508f67b789151365dfdbb89f25..909bc54870d6442ea9daf8e86d2dc97acfe4b93d 100644
--- a/src/responder/ifp/ifpsrv_util.c
+++ b/src/responder/ifp/ifpsrv_util.c
@@ -356,127 +356,12 @@ errno_t ifp_add_ldb_el_to_dict(DBusMessageIter *iter_dict,
     return EOK;
 }
 
-static inline bool
-attr_in_list(const char **list, size_t nlist, const char *str)
-{
-    size_t i;
-
-    for (i = 0; i < nlist; i++) {
-        if (strcasecmp(list[i], str) == 0) {
-            break;
-        }
-    }
-
-    return (i < nlist) ? true : false;
-}
-
 const char **
 ifp_parse_attr_list(TALLOC_CTX *mem_ctx, const char *conf_str)
 {
-    TALLOC_CTX *tmp_ctx;
-    errno_t ret;
-    const char **list = NULL;
-    const char **res = NULL;
-    int list_size;
-    char **conf_list = NULL;
-    int conf_list_size = 0;
-    const char **allow = NULL;
-    const char **deny = NULL;
-    int ai = 0, di = 0, li = 0;
-    int i;
     const char *defaults[] = IFP_DEFAULT_ATTRS;
 
-    tmp_ctx = talloc_new(NULL);
-    if (tmp_ctx == NULL) {
-        return NULL;
-    }
-
-    if (conf_str) {
-        ret = split_on_separator(tmp_ctx, conf_str, ',', true, true,
-                                 &conf_list, &conf_list_size);
-        if (ret != EOK) {
-            DEBUG(SSSDBG_OP_FAILURE,
-                  "Cannot parse attribute ACL list  %s: %d\n", conf_str, ret);
-            goto done;
-        }
-
-        allow = talloc_zero_array(tmp_ctx, const char *, conf_list_size);
-        deny = talloc_zero_array(tmp_ctx, const char *, conf_list_size);
-        if (allow == NULL || deny == NULL) {
-            goto done;
-        }
-    }
-
-    for (i = 0; i < conf_list_size; i++) {
-        switch (conf_list[i][0]) {
-            case '+':
-                allow[ai] = conf_list[i] + 1;
-                ai++;
-                continue;
-            case '-':
-                deny[di] = conf_list[i] + 1;
-                di++;
-                continue;
-            default:
-                DEBUG(SSSDBG_CRIT_FAILURE, "ACL values must start with "
-                      "either '+' (allow) or '-' (deny), got '%s'\n",
-                      conf_list[i]);
-                goto done;
-        }
-    }
-
-    /* Assume the output will have to hold defauls and all the configured,
-     * values, resize later
-     */
-    list_size = 0;
-    while (defaults[list_size]) {
-        list_size++;
-    }
-    list_size += conf_list_size;
-
-    list = talloc_zero_array(tmp_ctx, const char *, list_size + 1);
-    if (list == NULL) {
-        goto done;
-    }
-
-    /* Start by copying explicitly allowed attributes */
-    for (i = 0; i < ai; i++) {
-        /* if the attribute is explicitly denied, skip it */
-        if (attr_in_list(deny, di, allow[i])) {
-            continue;
-        }
-
-        list[li] = talloc_strdup(list, allow[i]);
-        if (list[li] == NULL) {
-            goto done;
-        }
-        li++;
-
-        DEBUG(SSSDBG_TRACE_INTERNAL,
-              "Added allowed attr %s to whitelist\n", allow[i]);
-    }
-
-    /* Add defaults */
-    for (i = 0; defaults[i]; i++) {
-        /* if the attribute is explicitly denied, skip it */
-        if (attr_in_list(deny, di, defaults[i])) {
-            continue;
-        }
-
-        list[li] = talloc_strdup(list, defaults[i]);
-        if (list[li] == NULL) {
-            goto done;
-        }
-        li++;
-
-        DEBUG(SSSDBG_TRACE_INTERNAL,
-              "Added default attr %s to whitelist\n", defaults[i]);
-    }
-
-    res = talloc_steal(mem_ctx, list);
-done:
-    talloc_free(tmp_ctx);
-    return res;
+    return parse_attr_list_ex(mem_ctx, conf_str, defaults);
 }
 
 bool
diff --git a/src/tests/cmocka/test_ifp.c b/src/tests/cmocka/test_ifp.c
index b0f6e09900a956a51c17d1c4cf1a7772dccc3a68..d6e41706d5f55414c0376bd04d299ec6ad73c11e 100644
--- a/src/tests/cmocka/test_ifp.c
+++ b/src/tests/cmocka/test_ifp.c
@@ -246,6 +246,29 @@ static void attr_parse_test(const char *expected[], const char *input)
     talloc_free(test_ctx);
 }
 
+static void attr_parse_test_ex(const char *expected[], const char *input,
+                               const char **defaults)
+{
+    const char **res;
+    TALLOC_CTX *test_ctx;
+
+    test_ctx = talloc_new(NULL);
+    assert_non_null(test_ctx);
+
+    res = parse_attr_list_ex(test_ctx, input, defaults);
+
+    if (expected) {
+        /* Positive test */
+        assert_non_null(res);
+        assert_string_list_equal(res, expected);
+    } else {
+        /* Negative test */
+        assert_null(res);
+    }
+
+    talloc_free(test_ctx);
+}
+
 void test_attr_acl(void **state)
 {
     /* Test defaults */
@@ -296,6 +319,33 @@ void test_attr_acl(void **state)
     attr_parse_test(NULL,  "missing_plus_or_minus");
 }
 
+void test_attr_acl_ex(void **state)
+{
+    /* Test defaults */
+    const char *exp_defaults[] = { "abc", "123", "xyz", NULL };
+    attr_parse_test_ex(exp_defaults, NULL, exp_defaults);
+
+    /* Test adding some attributes to the defaults */
+    const char *exp_add[] = { "telephoneNumber", "streetAddress",
+                              "abc", "123", "xyz",
+                              NULL };
+    attr_parse_test_ex(exp_add, "+telephoneNumber, +streetAddress",
+                       exp_defaults);
+
+    /* Test removing some attributes to the defaults */
+    const char *exp_rm[] = { "123", NULL };
+    attr_parse_test_ex(exp_rm, "-abc, -xyz", exp_defaults);
+
+    /* Test adding with empty defaults */
+    const char *exp_add_empty[] = { "telephoneNumber", "streetAddress",
+                                    NULL };
+    attr_parse_test_ex(exp_add_empty, "+telephoneNumber, +streetAddress", NULL);
+
+    /* Test removing with empty defaults */
+    const char *rm_all[] = { NULL };
+    attr_parse_test_ex(rm_all, "-telephoneNumber, -streetAddress", NULL);
+}
+
 void test_attr_allowed(void **state)
 {
     const char *whitelist[] = { "name", "gecos", NULL };
@@ -452,6 +502,7 @@ int main(int argc, const char *argv[])
         unit_test(test_path_prefix),
         unit_test(test_el_to_dict),
         unit_test(test_attr_acl),
+        unit_test(test_attr_acl_ex),
         unit_test(test_attr_allowed),
         unit_test(test_path_escape_unescape),
         unit_test_setup_teardown(test_reply_path,
-- 
1.9.3