diff options
-rw-r--r-- | Makefile.am | 5 | ||||
-rw-r--r-- | src/responder/common/responder.h | 2 | ||||
-rw-r--r-- | src/responder/common/responder_utils.c | 151 | ||||
-rw-r--r-- | src/responder/ifp/ifp_private.h | 3 | ||||
-rw-r--r-- | src/responder/ifp/ifpsrv_util.c | 117 | ||||
-rw-r--r-- | src/tests/cmocka/test_ifp.c | 51 |
6 files changed, 212 insertions, 117 deletions
diff --git a/Makefile.am b/Makefile.am index 61bf5cf95..ac8ad1566 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 e3c0f2267..02a215ced 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 000000000..815b61b39 --- /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 bf2015a97..fb1639c8d 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 c0ab686e4..909bc5487 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 b0f6e0990..d6e41706d 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, |