/* Authors: Yassir Elley Copyright (C) 2014 Red Hat SSSD tests: GPO unit tests 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 #include #include /* In order to access opaque types */ #include "providers/ad/ad_gpo.c" #include "tests/cmocka/common_mock.h" struct ad_gpo_test_ctx { struct ldb_context *ldb_ctx; }; static struct ad_gpo_test_ctx *test_ctx; void ad_gpo_test_setup(void **state) { assert_true(leak_check_setup()); test_ctx = talloc_zero(global_talloc_context, struct ad_gpo_test_ctx); assert_non_null(test_ctx); test_ctx->ldb_ctx = ldb_init(test_ctx, NULL); assert_non_null(test_ctx->ldb_ctx); } void ad_gpo_test_teardown(void **state) { talloc_free(test_ctx); assert_true(leak_check_teardown()); } struct som_list_result { const int result; const int num_soms; const char **som_dns; }; /* * Test parsing target dn into som components */ static void test_populate_som_list(const char *target_dn, struct som_list_result *expected) { errno_t ret; int i; int num_soms; struct gp_som **som_list = NULL; TALLOC_CTX *tmp_ctx; tmp_ctx = talloc_new(global_talloc_context); assert_non_null(tmp_ctx); check_leaks_push(tmp_ctx); ret = ad_gpo_populate_som_list(tmp_ctx, test_ctx->ldb_ctx, target_dn, &num_soms, &som_list); assert_int_equal(ret, expected->result); if (ret != EOK) { goto done; } assert_int_equal(num_soms, expected->num_soms); for (i=0; inum_soms; i++){ bool equal = true; if (strncmp(som_list[i]->som_dn, expected->som_dns[i], strlen(expected->som_dns[i])) != 0) { equal = false; } assert_int_equal(equal, true); } if (som_list) { talloc_free(som_list); } done: assert_true(check_leaks_pop(tmp_ctx) == true); talloc_free(tmp_ctx); } void test_populate_som_list_plain(void **state) { const char *som_dns[] = {"OU=West OU,OU=Sales OU,DC=foo,DC=com", "OU=Sales OU,DC=foo,DC=com", "DC=foo,DC=com"}; struct som_list_result expected = { .result = EOK, .num_soms = 3, .som_dns = som_dns }; test_populate_som_list("CN=F21-Client,OU=West OU,OU=Sales OU,DC=foo,DC=com", &expected); } void test_populate_som_list_malformed(void **state) { struct som_list_result expected = { .result = EINVAL, }; test_populate_som_list("malformed target dn", &expected); } struct gplink_list_result { const int result; const int num_gplinks; const char **gpo_dns; bool *enforced; }; /* * Test parsing raw_gplink_value into gplink components */ static void test_populate_gplink_list(const char *input_gplink_value, bool allow_enforced_only, struct gplink_list_result *expected) { errno_t ret; int i; struct gp_gplink **gplink_list = NULL; TALLOC_CTX *tmp_ctx; tmp_ctx = talloc_new(global_talloc_context); assert_non_null(tmp_ctx); check_leaks_push(tmp_ctx); char *raw_gplink_value = talloc_strdup(tmp_ctx, input_gplink_value); ret = ad_gpo_populate_gplink_list(tmp_ctx, NULL, raw_gplink_value, &gplink_list, allow_enforced_only); talloc_free(raw_gplink_value); assert_int_equal(ret, expected->result); if (ret != EOK) { goto done; } for (i=0; inum_gplinks; i++){ bool equal = true; if (strncmp(gplink_list[i]->gpo_dn, expected->gpo_dns[i], strlen(expected->gpo_dns[i])) != 0) { equal = false; } if (gplink_list[i]->enforced != expected->enforced[i]) equal = false; assert_int_equal(equal, true); } if (gplink_list) { talloc_free(gplink_list); } done: assert_true(check_leaks_pop(tmp_ctx) == true); talloc_free(tmp_ctx); } void test_populate_gplink_list_plain(void **state) { const char *gpo_dns[] = {"OU=Sales,DC=FOO,DC=COM", "DC=FOO,DC=COM"}; bool enforced[] = {false, true}; struct gplink_list_result expected = { .result = EOK, .num_gplinks = 2, .gpo_dns = gpo_dns, .enforced = enforced }; test_populate_gplink_list("[OU=Sales,DC=FOO,DC=COM;0][DC=FOO,DC=COM;2]", false, &expected); } void test_populate_gplink_list_with_ignored(void **state) { const char *gpo_dns[] = {"OU=Sales,DC=FOO,DC=COM"}; bool enforced[] = {false}; struct gplink_list_result expected = { .result = EOK, .num_gplinks = 1, .gpo_dns = gpo_dns, .enforced = enforced }; test_populate_gplink_list("[OU=Sales,DC=FOO,DC=COM;0][DC=ignored;1]", false, &expected); } void test_populate_gplink_list_with_allow_enforced(void **state) { const char *gpo_dns[] = {"DC=FOO,DC=COM"}; bool enforced[] = {true}; struct gplink_list_result expected = { .result = EOK, .num_gplinks = 1, .gpo_dns = gpo_dns, .enforced = enforced }; test_populate_gplink_list("[OU=Sales,DC=FOO,DC=COM;0][DC=FOO,DC=COM;2]", true, &expected); } void test_populate_gplink_list_malformed(void **state) { struct gplink_list_result expected = { .result = EINVAL, }; test_populate_gplink_list(NULL, false, &expected); test_populate_gplink_list("[malformed]", false, &expected); /* the GPLinkOptions value (after semicolon) must be between 0 and 3 */ test_populate_gplink_list("[gpo_dn; 4]", false, &expected); } /* * Test sid-matching logic */ static void test_ad_gpo_ace_includes_client_sid(const char *user_sid, const char **group_sids, int group_size, struct dom_sid ace_dom_sid, bool expected) { errno_t ret; enum idmap_error_code err; struct sss_idmap_ctx *idmap_ctx; bool includes_client_sid; TALLOC_CTX *tmp_ctx; tmp_ctx = talloc_new(global_talloc_context); assert_non_null(tmp_ctx); check_leaks_push(tmp_ctx); err = sss_idmap_init(sss_idmap_talloc, tmp_ctx, sss_idmap_talloc_free, &idmap_ctx); assert_int_equal(err, IDMAP_SUCCESS); ret = ad_gpo_ace_includes_client_sid(user_sid, group_sids, group_size, ace_dom_sid, idmap_ctx, &includes_client_sid); talloc_free(idmap_ctx); assert_int_equal(ret, EOK); assert_int_equal(includes_client_sid, expected); assert_true(check_leaks_pop(tmp_ctx) == true); talloc_free(tmp_ctx); } void test_ad_gpo_ace_includes_client_sid_true(void **state) { /* ace_dom_sid represents "S-1-5-21-2-3-4" */ struct dom_sid ace_dom_sid = {1, 4, {0, 0, 0, 0, 0, 5}, {21, 2, 3, 4}}; const char *user_sid = "S-1-5-21-1175337206-4250576914-2321192831-1103"; int group_size = 2; const char *group_sids[] = {"S-1-5-21-2-3-4", "S-1-5-21-2-3-5"}; test_ad_gpo_ace_includes_client_sid(user_sid, group_sids, group_size, ace_dom_sid, true); } void test_ad_gpo_ace_includes_client_sid_false(void **state) { /* ace_dom_sid represents "S-1-5-21-2-3-4" */ struct dom_sid ace_dom_sid = {1, 4, {0, 0, 0, 0, 0, 5}, {21, 2, 3, 4}}; const char *user_sid = "S-1-5-21-1175337206-4250576914-2321192831-1103"; int group_size = 2; const char *group_sids[] = {"S-1-5-21-2-3-5", "S-1-5-21-2-3-6"}; test_ad_gpo_ace_includes_client_sid(user_sid, group_sids, group_size, ace_dom_sid, false); } int main(int argc, const char *argv[]) { poptContext pc; int opt; struct poptOption long_options[] = { POPT_AUTOHELP SSSD_DEBUG_OPTS POPT_TABLEEND }; const UnitTest tests[] = { unit_test_setup_teardown(test_populate_som_list_plain, ad_gpo_test_setup, ad_gpo_test_teardown), unit_test_setup_teardown(test_populate_som_list_malformed, ad_gpo_test_setup, ad_gpo_test_teardown), unit_test_setup_teardown(test_populate_gplink_list_plain, ad_gpo_test_setup, ad_gpo_test_teardown), unit_test_setup_teardown(test_populate_gplink_list_with_ignored, ad_gpo_test_setup, ad_gpo_test_teardown), unit_test_setup_teardown(test_populate_gplink_list_with_allow_enforced, ad_gpo_test_setup, ad_gpo_test_teardown), unit_test_setup_teardown(test_populate_gplink_list_malformed, ad_gpo_test_setup, ad_gpo_test_teardown), unit_test_setup_teardown(test_ad_gpo_ace_includes_client_sid_true, ad_gpo_test_setup, ad_gpo_test_teardown), unit_test_setup_teardown(test_ad_gpo_ace_includes_client_sid_false, ad_gpo_test_setup, ad_gpo_test_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(); return run_tests(tests); }