From cfb6a115568ab24fe5df365d1436419b504111ec Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Mon, 6 Feb 2017 10:27:22 +0100 Subject: [PATCH 10/15] sysdb: add certmap related calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add sysdb calls to write and read data for the certificate mapping library to the cache. Related to https://pagure.io/SSSD/sssd/issue/3050 Reviewed-by: Jakub Hrozek Reviewed-by: Lukáš Slebodník --- Makefile.am | 17 ++ src/db/sysdb.h | 27 +++ src/db/sysdb_certmap.c | 425 ++++++++++++++++++++++++++++++++++ src/tests/cmocka/test_sysdb_certmap.c | 260 +++++++++++++++++++++ 4 files changed, 729 insertions(+) create mode 100644 src/db/sysdb_certmap.c create mode 100644 src/tests/cmocka/test_sysdb_certmap.c diff --git a/Makefile.am b/Makefile.am index f262cc24832358910dbb92ccd46f93c9eda8a295..bd0ca0d303e1742ad26c7648cd24e2c0135af34e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -254,6 +254,7 @@ if HAVE_CMOCKA test_sysdb_ts_cache \ test_sysdb_views \ test_sysdb_subdomains \ + test_sysdb_certmap \ test_sysdb_sudo \ test_sysdb_utils \ test_wbc_calls \ @@ -974,6 +975,7 @@ libsss_util_la_SOURCES = \ src/db/sysdb_ranges.c \ src/db/sysdb_idmap.c \ src/db/sysdb_gpo.c \ + src/db/sysdb_certmap.c \ src/monitor/monitor_sbus.c \ src/providers/dp_auth_util.c \ src/providers/dp_pam_data_util.c \ @@ -2773,6 +2775,21 @@ test_sysdb_subdomains_LDADD = \ libsss_test_common.la \ $(NULL) +test_sysdb_certmap_SOURCES = \ + src/tests/cmocka/test_sysdb_certmap.c \ + $(NULL) +test_sysdb_certmap_CFLAGS = \ + $(AM_CFLAGS) \ + $(NULL) +test_sysdb_certmap_LDADD = \ + $(CMOCKA_LIBS) \ + $(LDB_LIBS) \ + $(POPT_LIBS) \ + $(TALLOC_LIBS) \ + $(SSSD_INTERNAL_LTLIBS) \ + libsss_test_common.la \ + $(NULL) + test_sysdb_sudo_SOURCES = \ src/tests/cmocka/test_sysdb_sudo.c \ $(NULL) diff --git a/src/db/sysdb.h b/src/db/sysdb.h index 3db22b3689bf6ffd9a48e29c229916e3fac9ca1b..0cbb2c5c02355e9e9a4e73b075f92d16e4855045 100644 --- a/src/db/sysdb.h +++ b/src/db/sysdb.h @@ -39,6 +39,7 @@ #define SYSDB_NETGROUP_CONTAINER "cn=Netgroups" #define SYSDB_RANGE_CONTAINER "cn=ranges" #define SYSDB_VIEW_CONTAINER "cn=views" +#define SYSDB_CERTMAP_CONTAINER "cn=certmap" #define SYSDB_TMPL_USER_BASE SYSDB_USERS_CONTAINER","SYSDB_DOM_BASE #define SYSDB_TMPL_GROUP_BASE SYSDB_GROUPS_CONTAINER","SYSDB_DOM_BASE #define SYSDB_TMPL_CUSTOM_BASE SYSDB_CUSTOM_CONTAINER","SYSDB_DOM_BASE @@ -46,6 +47,7 @@ #define SYSDB_TMPL_RANGE_BASE SYSDB_RANGE_CONTAINER","SYSDB_BASE #define SYSDB_TMPL_VIEW_BASE SYSDB_VIEW_CONTAINER","SYSDB_BASE #define SYSDB_TMPL_VIEW_SEARCH_BASE "cn=%s,"SYSDB_TMPL_VIEW_BASE +#define SYSDB_TMPL_CERTMAP_BASE SYSDB_CERTMAP_CONTAINER","SYSDB_BASE #define SYSDB_SUBDOMAIN_CLASS "subdomain" #define SYSDB_USER_CLASS "user" @@ -58,6 +60,7 @@ #define SYSDB_ID_RANGE_CLASS "idRange" #define SYSDB_DOMAIN_ID_RANGE_CLASS "domainIDRange" #define SYSDB_TRUSTED_AD_DOMAIN_RANGE_CLASS "TrustedADDomainRange" +#define SYSDB_CERTMAP_CLASS "certificateMappingRule" #define SYSDB_DN "dn" #define SYSDB_NAME "name" @@ -158,6 +161,12 @@ #define SYSDB_DOMAIN_ID "domainID" #define SYSDB_ID_RANGE_TYPE "idRangeType" +#define SYSDB_CERTMAP_PRIORITY "priority" +#define SYSDB_CERTMAP_MATCHING_RULE "matchingRule" +#define SYSDB_CERTMAP_MAPPING_RULE "mappingRule" +#define SYSDB_CERTMAP_DOMAINS "domains" +#define SYSDB_CERTMAP_USER_NAME_HINT "userNameHint" + #define ORIGINALAD_PREFIX "originalAD" #define OVERRIDE_PREFIX "override" #define SYSDB_DEFAULT_OVERRIDE_NAME "defaultOverrideName" @@ -264,6 +273,7 @@ #define SYSDB_TMPL_CUSTOM SYSDB_NAME"=%s,cn=%s,"SYSDB_TMPL_CUSTOM_BASE #define SYSDB_TMPL_RANGE SYSDB_NAME"=%s,"SYSDB_TMPL_RANGE_BASE #define SYSDB_TMPL_OVERRIDE SYSDB_OVERRIDE_ANCHOR_UUID"=%s,"SYSDB_TMPL_VIEW_SEARCH_BASE +#define SYSDB_TMPL_CERTMAP SYSDB_NAME"=%s,"SYSDB_TMPL_CERTMAP_BASE #define SYSDB_MOD_ADD LDB_FLAG_MOD_ADD #define SYSDB_MOD_DEL LDB_FLAG_MOD_DELETE @@ -320,6 +330,15 @@ struct range_info { char *range_type; }; +struct certmap_info { + char *name; + uint32_t priority; + char *match_rule; + char *map_rule; + const char **domains; +}; + + /* These attributes are stored in the timestamp cache */ extern const char *sysdb_ts_cache_attrs[]; @@ -619,6 +638,14 @@ uint64_t sss_view_ldb_msg_find_attr_as_uint64(struct sss_domain_info *dom, const char *attr_name, uint64_t default_value); +errno_t sysdb_update_certmap(struct sysdb_ctx *sysdb, + struct certmap_info **certmaps, + bool user_name_hint); + +errno_t sysdb_get_certmap(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb, + struct certmap_info ***certmaps, + bool *user_name_hint); + /* Sysdb initialization. * call this function *only* once to initialize the database and get * the sysdb ctx */ diff --git a/src/db/sysdb_certmap.c b/src/db/sysdb_certmap.c new file mode 100644 index 0000000000000000000000000000000000000000..4917796b11c3967b4d147ebee7c7e83f09b872ce --- /dev/null +++ b/src/db/sysdb_certmap.c @@ -0,0 +1,425 @@ +/* + SSSD + + System Database - certificate mapping rules related calls + + Copyright (C) 2017 Sumit Bose + + 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 . +*/ + + +#include "util/util.h" +#include "db/sysdb_private.h" + +static errno_t sysdb_create_certmap_container(struct sysdb_ctx *sysdb, + bool user_name_hint) +{ + struct ldb_message *msg = NULL; + errno_t ret; + + msg = ldb_msg_new(sysdb); + if (msg == NULL) { + ret = ENOMEM; + goto done; + } + msg->dn = ldb_dn_new(msg, sysdb->ldb, SYSDB_TMPL_CERTMAP_BASE); + if (msg->dn == NULL) { + ret = ENOMEM; + goto done; + } + ret = ldb_msg_add_string(msg, "cn", "certmap"); + if (ret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(ret); + goto done; + } + + ret = ldb_msg_add_string(msg, SYSDB_CERTMAP_USER_NAME_HINT, + user_name_hint ? "TRUE" : "FALSE"); + if (ret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(ret); + goto done; + } + + /* do a synchronous add */ + ret = ldb_add(sysdb->ldb, msg); + if (ret != LDB_SUCCESS) { + DEBUG(SSSDBG_FATAL_FAILURE, + "Failed to add certmap container (%d, [%s])!\n", + ret, ldb_errstring(sysdb->ldb)); + ret = EIO; + goto done; + } + + ret = EOK; + +done: + talloc_free(msg); + + return ret; +} + +static errno_t sysdb_certmap_add(struct sysdb_ctx *sysdb, + struct certmap_info *certmap) +{ + struct ldb_message *msg; + struct ldb_message_element *el; + int ret; + TALLOC_CTX *tmp_ctx; + size_t c; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed"); + return ENOMEM; + } + + msg = ldb_msg_new(tmp_ctx); + if (msg == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_new failed.\n"); + ret = ENOMEM; + goto done; + } + + msg->dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, + SYSDB_TMPL_CERTMAP, certmap->name); + if (msg->dn == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new_fmt failed.\n"); + ret = ENOMEM; + goto done; + } + + ret = sysdb_add_string(msg, SYSDB_OBJECTCLASS, SYSDB_CERTMAP_CLASS); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_string failed.\n"); + goto done; + } + + ret = sysdb_add_string(msg, SYSDB_NAME, certmap->name); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_string failed.\n"); + goto done; + } + + if (certmap->map_rule != NULL) { + ret = sysdb_add_string(msg, SYSDB_CERTMAP_MAPPING_RULE, + certmap->map_rule); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_string failed.\n"); + goto done; + } + } + + if (certmap->match_rule != NULL) { + ret = sysdb_add_string(msg, SYSDB_CERTMAP_MATCHING_RULE, + certmap->match_rule); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_string failed.\n"); + goto done; + } + } + + if (certmap->domains != NULL) { + for (c = 0; certmap->domains[c] != NULL; c++); + el = talloc_zero(tmp_ctx, struct ldb_message_element); + if (el == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_zero failed.\n"); + ret = ENOMEM; + goto done; + } + + el->name = talloc_strdup(el, SYSDB_CERTMAP_DOMAINS); + if(el->name == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); + ret = ENOMEM; + goto done; + } + el->num_values = c; + el->values = talloc_zero_array(el, struct ldb_val, c + 1); + if (el->values == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_zero_array failed.\n"); + ret = ENOMEM; + goto done; + } + + for (c = 0; certmap->domains[c] != NULL; c++) { + el->values[c].data = (uint8_t *) talloc_strdup(el->values, + certmap->domains[c]); + if (el->values[c].data == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); + ret = ENOMEM; + goto done; + } + el->values[c].length = strlen(certmap->domains[c]); + } + + ret = ldb_msg_add(msg, el, LDB_FLAG_MOD_ADD); + if (ret != LDB_SUCCESS) { + DEBUG(SSSDBG_OP_FAILURE, "ldb_msg_add failed.\n"); + ret = sysdb_error_to_errno(ret); + goto done; + } + } + + ret = sysdb_add_ulong(msg, SYSDB_CERTMAP_PRIORITY, + (unsigned long)certmap->priority); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_add_ulong failed.\n"); + goto done; + } + + ret = ldb_add(sysdb->ldb, msg); + if (ret != LDB_SUCCESS) { + DEBUG(SSSDBG_OP_FAILURE, "ldb_add failed.\n"); + ret = sysdb_error_to_errno(ret); + goto done; + } + + ret = EOK; + +done: + if (ret) { + DEBUG(SSSDBG_TRACE_FUNC, "Error: %d (%s)\n", ret, sss_strerror(ret)); + } + talloc_zfree(tmp_ctx); + return ret; +} + +errno_t sysdb_update_certmap(struct sysdb_ctx *sysdb, + struct certmap_info **certmaps, + bool user_name_hint) +{ + size_t c; + struct ldb_dn *container_dn = NULL; + bool in_transaction = false; + int ret; + int sret; + + if (certmaps == NULL) { + return EINVAL; + } + + container_dn = ldb_dn_new(sysdb, sysdb->ldb, SYSDB_TMPL_CERTMAP_BASE); + if (container_dn == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed.\n"); + return ENOMEM; + } + + ret = sysdb_transaction_start(sysdb); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_transaction_start failed.\n"); + goto done; + } + in_transaction = true; + + ret = sysdb_delete_recursive(sysdb, container_dn, true); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_delete_recursive failed.\n"); + goto done; + } + ret = sysdb_create_certmap_container(sysdb, user_name_hint); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_create_certmap_container failed.\n"); + goto done; + } + + for (c = 0; certmaps[c] != NULL; c++) { + ret = sysdb_certmap_add(sysdb, certmaps[c]); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_certmap_add failed.\n"); + goto done; + } + } + + ret = sysdb_transaction_commit(sysdb); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_transaction_commit failed.\n"); + goto done; + } + in_transaction = false; + +done: + if (in_transaction) { + sret = sysdb_transaction_cancel(sysdb); + if (sret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Could not cancel transaction.\n"); + } + } + + talloc_free(container_dn); + + return ret; +} + +errno_t sysdb_get_certmap(TALLOC_CTX *mem_ctx, struct sysdb_ctx *sysdb, + struct certmap_info ***certmaps, bool *user_name_hint) +{ + size_t c; + size_t d; + struct ldb_dn *container_dn = NULL; + int ret; + struct certmap_info **maps; + TALLOC_CTX *tmp_ctx = NULL; + struct ldb_result *res; + const char *tmp_str; + uint64_t tmp_uint; + struct ldb_message_element *tmp_el; + const char *attrs[] = {SYSDB_NAME, + SYSDB_CERTMAP_PRIORITY, + SYSDB_CERTMAP_MATCHING_RULE, + SYSDB_CERTMAP_MAPPING_RULE, + SYSDB_CERTMAP_DOMAINS, + NULL}; + const char *config_attrs[] = {SYSDB_CERTMAP_USER_NAME_HINT, + NULL}; + size_t num_values; + bool hint = false; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + ret = ENOMEM; + goto done; + } + + container_dn = ldb_dn_new(tmp_ctx, sysdb->ldb, SYSDB_TMPL_CERTMAP_BASE); + if (container_dn == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed.\n"); + ret = ENOMEM; + goto done; + } + + ret = ldb_search(sysdb->ldb, tmp_ctx, &res, container_dn, LDB_SCOPE_BASE, + config_attrs, SYSDB_CERTMAP_USER_NAME_HINT"=*"); + if (ret != LDB_SUCCESS || res->count != 1) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Failed to read certmap config, skipping.\n"); + } else { + hint = ldb_msg_find_attr_as_bool(res->msgs[0], + SYSDB_CERTMAP_USER_NAME_HINT, false); + } + + ret = ldb_search(sysdb->ldb, tmp_ctx, &res, + container_dn, LDB_SCOPE_SUBTREE, + attrs, "objectclass=%s", SYSDB_CERTMAP_CLASS); + if (ret != LDB_SUCCESS) { + DEBUG(SSSDBG_OP_FAILURE, "ldb_search failed.\n"); + ret = EIO; + goto done; + } + + if (res->count == 0) { + DEBUG(SSSDBG_TRACE_FUNC, "No certificate maps found.\n"); + ret = ENOENT; + goto done; + } + + maps = talloc_zero_array(tmp_ctx, struct certmap_info *, res->count + 1); + if (maps == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_zero_array failed.\n"); + ret = ENOMEM; + goto done; + } + + for (c = 0; c < res->count; c++) { + maps[c] = talloc_zero(maps, struct certmap_info); + if (maps[c] == NULL) { + ret = ENOMEM; + goto done; + } + tmp_str = ldb_msg_find_attr_as_string(res->msgs[c], SYSDB_NAME, NULL); + if (tmp_str == NULL) { + DEBUG(SSSDBG_MINOR_FAILURE, "The object [%s] doesn't have a name.\n", + ldb_dn_get_linearized(res->msgs[c]->dn)); + ret = EINVAL; + goto done; + } + + maps[c]->name = talloc_strdup(maps, tmp_str); + if (maps[c]->name == NULL) { + ret = ENOMEM; + goto done; + } + + tmp_str = ldb_msg_find_attr_as_string(res->msgs[c], + SYSDB_CERTMAP_MAPPING_RULE, NULL); + if (tmp_str != NULL) { + maps[c]->map_rule = talloc_strdup(maps, tmp_str); + if (maps[c]->map_rule == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); + ret = ENOMEM; + goto done; + } + } + + tmp_str = ldb_msg_find_attr_as_string(res->msgs[c], + SYSDB_CERTMAP_MATCHING_RULE, NULL); + if (tmp_str != NULL) { + maps[c]->match_rule = talloc_strdup(maps, tmp_str); + if (maps[c]->match_rule == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); + ret = ENOMEM; + goto done; + } + } + + tmp_uint = ldb_msg_find_attr_as_uint64(res->msgs[c], + SYSDB_CERTMAP_PRIORITY, + (uint64_t) -1); + if (tmp_uint != (uint64_t) -1) { + if (tmp_uint >= UINT32_MAX) { + DEBUG(SSSDBG_OP_FAILURE, "Priority value [%lu] too large.\n", + (unsigned long) tmp_uint); + ret = EINVAL; + goto done; + } + + maps[c]->priority = (uint32_t) tmp_uint; + } + + tmp_el = ldb_msg_find_element(res->msgs[c], SYSDB_CERTMAP_DOMAINS); + if (tmp_el != NULL) { + num_values = tmp_el->num_values; + } else { + num_values = 0; + } + + maps[c]->domains = talloc_zero_array(maps[c], const char *, + num_values + 1); + if (maps[c]->domains == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_zero_array failed.\n"); + ret = ENOMEM; + goto done; + } + + for (d = 0; d < num_values; d++) { + maps[c]->domains[d] = talloc_strndup(maps[c]->domains, + (char *) tmp_el->values[d].data, + tmp_el->values[d].length); + if (maps[c]->domains[d] == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n"); + ret = ENOMEM; + goto done; + } + } + } + + *certmaps = talloc_steal(mem_ctx, maps); + *user_name_hint = hint; + ret = EOK; + +done: + talloc_free(tmp_ctx); + + return ret; +} diff --git a/src/tests/cmocka/test_sysdb_certmap.c b/src/tests/cmocka/test_sysdb_certmap.c new file mode 100644 index 0000000000000000000000000000000000000000..fb07165561779226935f436c308c85abfc305635 --- /dev/null +++ b/src/tests/cmocka/test_sysdb_certmap.c @@ -0,0 +1,260 @@ +/* + SSSD + + sysdb_certmap - Tests for sysdb certmap realted calls + + Authors: + Jakub Hrozek + + Copyright (C) 2017 Red Hat + + 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 . +*/ + +#include +#include +#include +#include +#include + +#include "tests/cmocka/common_mock.h" +#include "tests/common.h" + +#define TESTS_PATH "certmap_" BASE_FILE_STEM +#define TEST_CONF_DB "test_sysdb_certmap.ldb" +#define TEST_ID_PROVIDER "ldap" +#define TEST_DOM_NAME "certmap_test" + +struct certmap_test_ctx { + struct sss_test_ctx *tctx; +}; + +static int test_sysdb_setup(void **state) +{ + struct certmap_test_ctx *test_ctx; + struct sss_test_conf_param params[] = { + { NULL, NULL }, /* Sentinel */ + }; + + assert_true(leak_check_setup()); + + test_ctx = talloc_zero(global_talloc_context, + struct certmap_test_ctx); + assert_non_null(test_ctx); + check_leaks_push(test_ctx); + + test_dom_suite_setup(TESTS_PATH); + + test_ctx->tctx = create_dom_test_ctx(test_ctx, TESTS_PATH, + TEST_CONF_DB, TEST_DOM_NAME, + TEST_ID_PROVIDER, params); + assert_non_null(test_ctx->tctx); + + *state = test_ctx; + return 0; +} + +static int test_sysdb_teardown(void **state) +{ + struct certmap_test_ctx *test_ctx = + talloc_get_type(*state, struct certmap_test_ctx); + + test_dom_suite_cleanup(TESTS_PATH, TEST_CONF_DB, TEST_DOM_NAME); + talloc_free(test_ctx->tctx); + assert_true(check_leaks_pop(test_ctx)); + talloc_free(test_ctx); + assert_true(leak_check_teardown()); + return 0; +} + +static void test_sysdb_get_certmap_not_exists(void **state) +{ + int ret; + struct certmap_info **certmap; + bool user_name_hint; + struct certmap_test_ctx *ctctx = talloc_get_type(*state, + struct certmap_test_ctx); + + ret = sysdb_get_certmap(ctctx, ctctx->tctx->sysdb, &certmap, + &user_name_hint); + assert_int_equal(ret, ENOENT); + +} + +static void check_certmap(struct certmap_info *m, struct certmap_info *r, + size_t exp_domains) +{ + size_t d; + + assert_non_null(r); + assert_non_null(m); + assert_string_equal(m->name, r->name); + + if (r->map_rule == NULL) { + assert_null(m->map_rule); + } else { + assert_string_equal(m->map_rule, r->map_rule); + } + + if (r->match_rule == NULL) { + assert_null(m->match_rule); + } else { + assert_string_equal(m->match_rule, r->match_rule); + } + + assert_int_equal(m->priority, r->priority); + assert_non_null(m->domains); + if (r->domains == NULL) { + assert_null(m->domains[0]); + } else { + for (d = 0; r->domains[d]; d++) { + assert_non_null(m->domains[d]); + assert_true(string_in_list(m->domains[d], discard_const(r->domains), + true)); + } + + assert_int_equal(d, exp_domains); + } + +} + +static void test_sysdb_update_certmap(void **state) +{ + int ret; + const char *domains[] = { "dom1.test", "dom2.test", "dom3.test", NULL }; + struct certmap_info map_a = { discard_const("map_a"), 11, discard_const("abc"), discard_const("def"), NULL }; + struct certmap_info map_b = { discard_const("map_b"), 22, discard_const("abc"), NULL, domains }; + struct certmap_info *certmap_empty[] = { NULL }; + struct certmap_info *certmap_a[] = { &map_a, NULL }; + struct certmap_info *certmap_b[] = { &map_b, NULL }; + struct certmap_info *certmap_ab[] = { &map_a, &map_b, NULL }; + struct certmap_info **certmap; + struct certmap_test_ctx *ctctx = talloc_get_type(*state, + struct certmap_test_ctx); + bool user_name_hint; + + ret = sysdb_update_certmap(ctctx->tctx->sysdb, NULL, false); + assert_int_equal(ret, EINVAL); + + ret = sysdb_update_certmap(ctctx->tctx->sysdb, certmap_empty, false); + assert_int_equal(ret, EOK); + + ret = sysdb_get_certmap(ctctx, ctctx->tctx->sysdb, &certmap, + &user_name_hint); + assert_int_equal(ret, ENOENT); + + ret = sysdb_update_certmap(ctctx->tctx->sysdb, certmap_a, false); + assert_int_equal(ret, EOK); + + ret = sysdb_get_certmap(ctctx, ctctx->tctx->sysdb, &certmap, + &user_name_hint); + assert_int_equal(ret, EOK); + assert_false(user_name_hint); + assert_non_null(certmap); + assert_non_null(certmap[0]); + assert_string_equal(certmap[0]->name, map_a.name); + assert_string_equal(certmap[0]->map_rule, map_a.map_rule); + assert_string_equal(certmap[0]->match_rule, map_a.match_rule); + assert_int_equal(certmap[0]->priority, map_a.priority); + assert_non_null(certmap[0]->domains); + assert_null(certmap[0]->domains[0]); + assert_null(certmap[1]); + check_certmap(certmap[0], &map_a, 0); + talloc_free(certmap); + + ret = sysdb_update_certmap(ctctx->tctx->sysdb, certmap_b, true); + assert_int_equal(ret, EOK); + + ret = sysdb_get_certmap(ctctx, ctctx->tctx->sysdb, &certmap, + &user_name_hint); + assert_int_equal(ret, EOK); + assert_true(user_name_hint); + assert_non_null(certmap); + assert_non_null(certmap[0]); + + check_certmap(certmap[0], &map_b, 3); + assert_null(certmap[1]); + talloc_free(certmap); + + ret = sysdb_update_certmap(ctctx->tctx->sysdb, certmap_ab, false); + assert_int_equal(ret, EOK); + + ret = sysdb_get_certmap(ctctx, ctctx->tctx->sysdb, &certmap, + &user_name_hint); + assert_int_equal(ret, EOK); + assert_false(user_name_hint); + assert_non_null(certmap); + assert_non_null(certmap[0]); + assert_non_null(certmap[1]); + assert_null(certmap[2]); + if (strcmp(certmap[0]->name, "map_a") == 0) { + check_certmap(certmap[0], &map_a, 0); + check_certmap(certmap[1], &map_b, 3); + } else { + check_certmap(certmap[0], &map_b, 3); + check_certmap(certmap[1], &map_a, 0); + } + talloc_free(certmap); +} + +int main(int argc, const char *argv[]) +{ + int rv; + int no_cleanup = 0; + poptContext pc; + int opt; + struct poptOption long_options[] = { + POPT_AUTOHELP + SSSD_DEBUG_OPTS + {"no-cleanup", 'n', POPT_ARG_NONE, &no_cleanup, 0, + _("Do not delete the test database after a test run"), NULL }, + POPT_TABLEEND + }; + + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown(test_sysdb_get_certmap_not_exists, + test_sysdb_setup, + test_sysdb_teardown), + cmocka_unit_test_setup_teardown(test_sysdb_update_certmap, + test_sysdb_setup, + test_sysdb_teardown), + }; + + /* Set debug level to invalid value so we can deside if -d 0 was used. */ + debug_level = SSSDBG_INVALID; + + pc = poptGetContext(argv[0], argc, argv, long_options, 0); + while((opt = poptGetNextOpt(pc)) != -1) { + switch(opt) { + default: + fprintf(stderr, "\nInvalid option %s: %s\n\n", + poptBadOption(pc, 0), poptStrerror(opt)); + poptPrintUsage(pc, stderr, 0); + return 1; + } + } + poptFreeContext(pc); + + DEBUG_CLI_INIT(debug_level); + + tests_set_cwd(); + test_dom_suite_cleanup(TESTS_PATH, TEST_CONF_DB, LOCAL_SYSDB_FILE); + test_dom_suite_setup(TESTS_PATH); + rv = cmocka_run_group_tests(tests, NULL, NULL); + + if (rv == 0 && no_cleanup == 0) { + test_dom_suite_cleanup(TESTS_PATH, TEST_CONF_DB, LOCAL_SYSDB_FILE); + } + return rv; +} -- 2.9.3