diff --git a/Add-unit-tests-for-simple-access-test-by-groups.patch b/Add-unit-tests-for-simple-access-test-by-groups.patch deleted file mode 100644 index dcf284f..0000000 --- a/Add-unit-tests-for-simple-access-test-by-groups.patch +++ /dev/null @@ -1,414 +0,0 @@ -From e5f0ef211e81fcd7a87d5e37b0aadca50201c6d6 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Sun, 3 Mar 2013 21:43:44 +0100 -Subject: Add unit tests for simple access test by groups - -I realized that the current unit tests for the simple access provider -only tested the user directives. To have a baseline and be able to -detect new bugs in the upcoming patch, I implemented unit tests for the -group lists, too. -(cherry picked from commit 754b09b5444e6da88ed58d6deaed8b815e268b6b) ---- - src/tests/simple_access-tests.c | 285 +++++++++++++++++++++++++++++++++++----- - 1 file changed, 253 insertions(+), 32 deletions(-) - -diff --git a/src/tests/simple_access-tests.c b/src/tests/simple_access-tests.c -index c61814e..577c6d3 100644 ---- a/src/tests/simple_access-tests.c -+++ b/src/tests/simple_access-tests.c -@@ -30,39 +30,152 @@ - #include "providers/simple/simple_access.h" - #include "tests/common.h" - -+#define TESTS_PATH "tests_simple_access" -+#define TEST_CONF_FILE "tests_conf.ldb" -+ - const char *ulist_1[] = {"u1", "u2", NULL}; -+const char *glist_1[] = {"g1", "g2", NULL}; -+ -+struct simple_test_ctx *test_ctx = NULL; -+ -+struct simple_test_ctx { -+ struct sysdb_ctx *sysdb; -+ struct confdb_ctx *confdb; - --struct simple_ctx *ctx = NULL; -+ struct simple_ctx *ctx; -+}; - - void setup_simple(void) - { -- fail_unless(ctx == NULL, "Simple context already initialized."); -- ctx = talloc_zero(NULL, struct simple_ctx); -- fail_unless(ctx != NULL, "Cannot create simple context."); -- -- ctx->domain = talloc_zero(ctx, struct sss_domain_info); -- fail_unless(ctx != NULL, "Cannot create domain in simple context."); -- ctx->domain->case_sensitive = true; -+ errno_t ret; -+ char *conf_db; -+ const char *val[2]; -+ val[1] = NULL; -+ -+ /* Create tests directory if it doesn't exist */ -+ /* (relative to current dir) */ -+ ret = mkdir(TESTS_PATH, 0775); -+ fail_if(ret == -1 && errno != EEXIST, -+ "Could not create %s directory", TESTS_PATH); -+ -+ fail_unless(test_ctx == NULL, "Simple context already initialized."); -+ test_ctx = talloc_zero(NULL, struct simple_test_ctx); -+ fail_unless(test_ctx != NULL, "Cannot create simple test context."); -+ -+ test_ctx->ctx = talloc_zero(test_ctx, struct simple_ctx); -+ fail_unless(test_ctx->ctx != NULL, "Cannot create simple context."); -+ -+ conf_db = talloc_asprintf(test_ctx, "%s/%s", TESTS_PATH, TEST_CONF_FILE); -+ fail_if(conf_db == NULL, "Out of memory, aborting!"); -+ DEBUG(SSSDBG_TRACE_LIBS, ("CONFDB: %s\n", conf_db)); -+ -+ /* Connect to the conf db */ -+ ret = confdb_init(test_ctx, &test_ctx->confdb, conf_db); -+ fail_if(ret != EOK, "Could not initialize connection to the confdb"); -+ -+ val[0] = "LOCAL"; -+ ret = confdb_add_param(test_ctx->confdb, true, -+ "config/sssd", "domains", val); -+ fail_if(ret != EOK, "Could not initialize domains placeholder"); -+ -+ val[0] = "local"; -+ ret = confdb_add_param(test_ctx->confdb, true, -+ "config/domain/LOCAL", "id_provider", val); -+ fail_if(ret != EOK, "Could not initialize provider"); -+ -+ val[0] = "TRUE"; -+ ret = confdb_add_param(test_ctx->confdb, true, -+ "config/domain/LOCAL", "enumerate", val); -+ fail_if(ret != EOK, "Could not initialize LOCAL domain"); -+ -+ val[0] = "TRUE"; -+ ret = confdb_add_param(test_ctx->confdb, true, -+ "config/domain/LOCAL", "cache_credentials", val); -+ fail_if(ret != EOK, "Could not initialize LOCAL domain"); -+ -+ ret = sysdb_init_domain_and_sysdb(test_ctx, test_ctx->confdb, "local", -+ TESTS_PATH, -+ &test_ctx->ctx->domain, &test_ctx->ctx->sysdb); -+ fail_if(ret != EOK, "Could not initialize connection to the sysdb (%d)", ret); -+ test_ctx->ctx->domain->case_sensitive = true; - } - - void teardown_simple(void) - { - int ret; -- fail_unless(ctx != NULL, "Simple context already freed."); -- ret = talloc_free(ctx); -- ctx = NULL; -+ fail_unless(test_ctx != NULL, "Simple context already freed."); -+ ret = talloc_free(test_ctx); -+ test_ctx = NULL; - fail_unless(ret == 0, "Connot free simple context."); - } - -+void setup_simple_group(void) -+{ -+ errno_t ret; -+ -+ setup_simple(); -+ -+ /* Add test users u1 and u2 that would be members of test groups -+ * g1 and g2 respectively */ -+ ret = sysdb_store_user(test_ctx->ctx->sysdb, -+ "u1", NULL, 123, 0, "u1", "/home/u1", -+ "/bin/bash", NULL, NULL, NULL, -1, 0); -+ fail_if(ret != EOK, "Could not add u1"); -+ -+ ret = sysdb_store_user(test_ctx->ctx->sysdb, -+ "u2", NULL, 456, 0, "u1", "/home/u1", -+ "/bin/bash", NULL, NULL, NULL, -1, 0); -+ fail_if(ret != EOK, "Could not add u2"); -+ -+ ret = sysdb_store_user(test_ctx->ctx->sysdb, -+ "u3", NULL, 789, 0, "u1", "/home/u1", -+ "/bin/bash", NULL, NULL, NULL, -1, 0); -+ fail_if(ret != EOK, "Could not add u3"); -+ -+ ret = sysdb_add_group(test_ctx->ctx->sysdb, -+ "g1", 321, NULL, 0, 0); -+ fail_if(ret != EOK, "Could not add g1"); -+ -+ ret = sysdb_add_group(test_ctx->ctx->sysdb, -+ "g2", 654, NULL, 0, 0); -+ fail_if(ret != EOK, "Could not add g2"); -+ -+ ret = sysdb_add_group_member(test_ctx->ctx->sysdb, -+ "g1", "u1", SYSDB_MEMBER_USER); -+ fail_if(ret != EOK, "Could not add u1 to g1"); -+ -+ ret = sysdb_add_group_member(test_ctx->ctx->sysdb, -+ "g2", "u2", SYSDB_MEMBER_USER); -+ fail_if(ret != EOK, "Could not add u2 to g2"); -+} -+ -+void teardown_simple_group(void) -+{ -+ errno_t ret; -+ -+ ret = sysdb_delete_user(test_ctx->ctx->sysdb, "u1", 0); -+ fail_if(ret != EOK, "Could not delete u1"); -+ ret = sysdb_delete_user(test_ctx->ctx->sysdb, "u2", 0); -+ fail_if(ret != EOK, "Could not delete u2"); -+ ret = sysdb_delete_user(test_ctx->ctx->sysdb, "u3", 0); -+ fail_if(ret != EOK, "Could not delete u3"); -+ ret = sysdb_delete_group(test_ctx->ctx->sysdb, "g1", 0); -+ fail_if(ret != EOK, "Could not delete g1"); -+ ret = sysdb_delete_group(test_ctx->ctx->sysdb, "g2", 0); -+ fail_if(ret != EOK, "Could not delete g2"); -+ -+ teardown_simple(); -+} -+ - START_TEST(test_both_empty) - { - int ret; - bool access_granted = false; - -- ctx->allow_users = NULL; -- ctx->deny_users = NULL; -+ test_ctx->ctx->allow_users = NULL; -+ test_ctx->ctx->deny_users = NULL; - -- ret = simple_access_check(ctx, "u1", &access_granted); -+ ret = simple_access_check(test_ctx->ctx, "u1", &access_granted); - fail_unless(ret == EOK, "access_simple_check failed."); - fail_unless(access_granted == true, "Access denied " - "while both lists are empty."); -@@ -74,15 +187,15 @@ START_TEST(test_allow_empty) - int ret; - bool access_granted = true; - -- ctx->allow_users = NULL; -- ctx->deny_users = discard_const(ulist_1); -+ test_ctx->ctx->allow_users = NULL; -+ test_ctx->ctx->deny_users = discard_const(ulist_1); - -- ret = simple_access_check(ctx, "u1", &access_granted); -+ ret = simple_access_check(test_ctx->ctx, "u1", &access_granted); - fail_unless(ret == EOK, "access_simple_check failed."); - fail_unless(access_granted == false, "Access granted " - "while user is in deny list."); - -- ret = simple_access_check(ctx, "u3", &access_granted); -+ ret = simple_access_check(test_ctx->ctx, "u3", &access_granted); - fail_unless(ret == EOK, "access_simple_check failed."); - fail_unless(access_granted == true, "Access denied " - "while user is not in deny list."); -@@ -94,15 +207,15 @@ START_TEST(test_deny_empty) - int ret; - bool access_granted = false; - -- ctx->allow_users = discard_const(ulist_1); -- ctx->deny_users = NULL; -+ test_ctx->ctx->allow_users = discard_const(ulist_1); -+ test_ctx->ctx->deny_users = NULL; - -- ret = simple_access_check(ctx, "u1", &access_granted); -+ ret = simple_access_check(test_ctx->ctx, "u1", &access_granted); - fail_unless(ret == EOK, "access_simple_check failed."); - fail_unless(access_granted == true, "Access denied " - "while user is in allow list."); - -- ret = simple_access_check(ctx, "u3", &access_granted); -+ ret = simple_access_check(test_ctx->ctx, "u3", &access_granted); - fail_unless(ret == EOK, "access_simple_check failed."); - fail_unless(access_granted == false, "Access granted " - "while user is not in allow list."); -@@ -114,15 +227,15 @@ START_TEST(test_both_set) - int ret; - bool access_granted = false; - -- ctx->allow_users = discard_const(ulist_1); -- ctx->deny_users = discard_const(ulist_1); -+ test_ctx->ctx->allow_users = discard_const(ulist_1); -+ test_ctx->ctx->deny_users = discard_const(ulist_1); - -- ret = simple_access_check(ctx, "u1", &access_granted); -+ ret = simple_access_check(test_ctx->ctx, "u1", &access_granted); - fail_unless(ret == EOK, "access_simple_check failed."); - fail_unless(access_granted == false, "Access granted " - "while user is in deny list."); - -- ret = simple_access_check(ctx, "u3", &access_granted); -+ ret = simple_access_check(test_ctx->ctx, "u3", &access_granted); - fail_unless(ret == EOK, "access_simple_check failed."); - fail_unless(access_granted == false, "Access granted " - "while user is not in allow list."); -@@ -134,18 +247,18 @@ START_TEST(test_case) - int ret; - bool access_granted = false; - -- ctx->allow_users = discard_const(ulist_1); -- ctx->deny_users = NULL; -+ test_ctx->ctx->allow_users = discard_const(ulist_1); -+ test_ctx->ctx->deny_users = NULL; - -- ret = simple_access_check(ctx, "U1", &access_granted); -+ ret = simple_access_check(test_ctx->ctx, "U1", &access_granted); - fail_unless(ret == EOK, "access_simple_check failed."); - fail_unless(access_granted == false, "Access granted " - "for user with different case " - "in case-sensitive domain"); - -- ctx->domain->case_sensitive = false; -+ test_ctx->ctx->domain->case_sensitive = false; - -- ret = simple_access_check(ctx, "U1", &access_granted); -+ ret = simple_access_check(test_ctx->ctx, "U1", &access_granted); - fail_unless(ret == EOK, "access_simple_check failed."); - fail_unless(access_granted == true, "Access denied " - "for user with different case " -@@ -153,11 +266,95 @@ START_TEST(test_case) - } - END_TEST - -+START_TEST(test_group_allow_empty) -+{ -+ int ret; -+ bool access_granted = true; -+ -+ test_ctx->ctx->allow_groups = NULL; -+ test_ctx->ctx->deny_groups = discard_const(glist_1); -+ -+ ret = simple_access_check(test_ctx->ctx, "u1", &access_granted); -+ fail_unless(ret == EOK, "access_simple_check failed."); -+ fail_unless(access_granted == false, "Access granted " -+ "while group is in deny list."); -+ -+ ret = simple_access_check(test_ctx->ctx, "u3", &access_granted); -+ fail_unless(ret == EOK, "access_simple_check failed."); -+ fail_unless(access_granted == true, "Access denied " -+ "while group is not in deny list."); -+} -+END_TEST -+ -+START_TEST(test_group_deny_empty) -+{ -+ int ret; -+ bool access_granted = false; -+ -+ test_ctx->ctx->allow_groups = discard_const(glist_1); -+ test_ctx->ctx->deny_groups = NULL; -+ -+ ret = simple_access_check(test_ctx->ctx, "u1", &access_granted); -+ fail_unless(ret == EOK, "access_simple_check failed."); -+ fail_unless(access_granted == true, "Access denied " -+ "while group is in allow list."); -+ -+ ret = simple_access_check(test_ctx->ctx, "u3", &access_granted); -+ fail_unless(ret == EOK, "access_simple_check failed."); -+ fail_unless(access_granted == false, "Access granted " -+ "while group is not in allow list."); -+} -+END_TEST -+ -+START_TEST(test_group_both_set) -+{ -+ int ret; -+ bool access_granted = false; -+ -+ test_ctx->ctx->allow_groups = discard_const(ulist_1); -+ test_ctx->ctx->deny_groups = discard_const(ulist_1); -+ -+ ret = simple_access_check(test_ctx->ctx, "u1", &access_granted); -+ fail_unless(ret == EOK, "access_simple_check failed."); -+ fail_unless(access_granted == false, "Access granted " -+ "while group is in deny list."); -+ -+ ret = simple_access_check(test_ctx->ctx, "u3", &access_granted); -+ fail_unless(ret == EOK, "access_simple_check failed."); -+ fail_unless(access_granted == false, "Access granted " -+ "while group is not in allow list."); -+} -+END_TEST -+ -+START_TEST(test_group_case) -+{ -+ int ret; -+ bool access_granted = false; -+ -+ test_ctx->ctx->allow_groups = discard_const(ulist_1); -+ test_ctx->ctx->deny_groups = NULL; -+ -+ ret = simple_access_check(test_ctx->ctx, "U1", &access_granted); -+ fail_unless(ret == EOK, "access_simple_check failed."); -+ fail_unless(access_granted == false, "Access granted " -+ "for group with different case " -+ "in case-sensitive domain"); -+ -+ test_ctx->ctx->domain->case_sensitive = false; -+ -+ ret = simple_access_check(test_ctx->ctx, "U1", &access_granted); -+ fail_unless(ret == EOK, "access_simple_check failed."); -+ fail_unless(access_granted == true, "Access denied " -+ "for group with different case " -+ "in case-insensitive domain"); -+} -+END_TEST -+ - Suite *access_simple_suite (void) - { - Suite *s = suite_create("access_simple"); - -- TCase *tc_allow_deny = tcase_create("allow/deny"); -+ TCase *tc_allow_deny = tcase_create("user allow/deny"); - tcase_add_checked_fixture(tc_allow_deny, setup_simple, teardown_simple); - tcase_add_test(tc_allow_deny, test_both_empty); - tcase_add_test(tc_allow_deny, test_allow_empty); -@@ -166,6 +363,15 @@ Suite *access_simple_suite (void) - tcase_add_test(tc_allow_deny, test_case); - suite_add_tcase(s, tc_allow_deny); - -+ TCase *tc_grp_allow_deny = tcase_create("group allow/deny"); -+ tcase_add_checked_fixture(tc_grp_allow_deny, -+ setup_simple_group, teardown_simple_group); -+ tcase_add_test(tc_grp_allow_deny, test_group_allow_empty); -+ tcase_add_test(tc_grp_allow_deny, test_group_deny_empty); -+ tcase_add_test(tc_grp_allow_deny, test_group_both_set); -+ tcase_add_test(tc_grp_allow_deny, test_group_case); -+ suite_add_tcase(s, tc_grp_allow_deny); -+ - return s; - } - -@@ -174,6 +380,7 @@ int main(int argc, const char *argv[]) - int opt; - poptContext pc; - int number_failed; -+ int ret; - - struct poptOption long_options[] = { - POPT_AUTOHELP -@@ -205,6 +412,20 @@ int main(int argc, const char *argv[]) - srunner_run_all(sr, CK_ENV); - number_failed = srunner_ntests_failed(sr); - srunner_free(sr); -+ -+ ret = unlink(TESTS_PATH"/"TEST_CONF_FILE); -+ if (ret != EOK) { -+ fprintf(stderr, "Could not delete the test config ldb file (%d) (%s)\n", -+ errno, strerror(errno)); -+ return EXIT_FAILURE; -+ } -+ ret = unlink(TESTS_PATH"/"LOCAL_SYSDB_FILE); -+ if (ret != EOK) { -+ fprintf(stderr, "Could not delete the test config ldb file (%d) (%s)\n", -+ errno, strerror(errno)); -+ return EXIT_FAILURE; -+ } -+ - return (number_failed==0 ? EXIT_SUCCESS : EXIT_FAILURE); - } - --- -1.8.1.4 - diff --git a/Do-not-compile-main-in-DP-if-UNIT_TESTING-is-defined.patch b/Do-not-compile-main-in-DP-if-UNIT_TESTING-is-defined.patch deleted file mode 100644 index d66871b..0000000 --- a/Do-not-compile-main-in-DP-if-UNIT_TESTING-is-defined.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 8dfcfe629db83eb58dd6613aa174222cb853afb1 Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Mon, 4 Mar 2013 16:37:04 +0100 -Subject: Do not compile main() in DP if UNIT_TESTING is defined - -The simple access provider unit tests now need to link against the Data -Provider when they start using the be_file_account_request() function. -But then we would start having conflicts as at least the main() -functions would clash. - -If UNIT_TESTING is defined, then the data_provider_be.c module does not -contain the main() function and can be linked against directly from -another module that contains its own main() function -(cherry picked from commit 26590d31f492dbbd36be6d0bde46a4bd3b221edb) ---- - src/providers/data_provider_be.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c -index f85a04d..33590ae 100644 ---- a/src/providers/data_provider_be.c -+++ b/src/providers/data_provider_be.c -@@ -2651,6 +2651,7 @@ fail: - return ret; - } - -+#ifndef UNIT_TESTING - int main(int argc, const char *argv[]) - { - int opt; -@@ -2732,6 +2733,7 @@ int main(int argc, const char *argv[]) - - return 0; - } -+#endif - - static int data_provider_res_init(DBusMessage *message, - struct sbus_connection *conn) --- -1.8.1.4 - diff --git a/Provide-a-be_get_account_info_send-function.patch b/Provide-a-be_get_account_info_send-function.patch deleted file mode 100644 index 5e75c49..0000000 --- a/Provide-a-be_get_account_info_send-function.patch +++ /dev/null @@ -1,237 +0,0 @@ -From 455737c0b4b0c1bfeed54f2e27e397ce403acbca Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Fri, 22 Feb 2013 11:01:38 +0100 -Subject: Provide a be_get_account_info_send function - -In order to resolve group names in the simple access provider we need to -contact the Data Provider in a generic fashion from the access provider. -We can't call any particular implementation (like sdap_generic_send()) -because we have no idea what kind of provider is configured as the -id_provider. - -This patch splits introduces the be_file_account_request() function into -the data_provider_be module and makes it public. - -A future patch should make the be_get_account_info function use the -be_get_account_info_send function. -(cherry picked from commit b63830b142053f99bfe954d4be5a2b0f68ce3a93) ---- - src/providers/data_provider_be.c | 153 ++++++++++++++++++++++++++++++++++----- - src/providers/dp_backend.h | 15 ++++ - 2 files changed, 149 insertions(+), 19 deletions(-) - -diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c -index b261bf8..f85a04d 100644 ---- a/src/providers/data_provider_be.c -+++ b/src/providers/data_provider_be.c -@@ -717,6 +717,34 @@ static errno_t be_initgroups_prereq(struct be_req *be_req) - } - - static errno_t -+be_file_account_request(struct be_req *be_req, struct be_acct_req *ar) -+{ -+ errno_t ret; -+ struct be_ctx *be_ctx = be_req->be_ctx; -+ -+ be_req->req_data = ar; -+ -+ /* see if we need a pre request call, only done for initgroups for now */ -+ if ((ar->entry_type & 0xFF) == BE_REQ_INITGROUPS) { -+ ret = be_initgroups_prereq(be_req); -+ if (ret) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("Prerequest failed")); -+ return ret; -+ } -+ } -+ -+ /* process request */ -+ ret = be_file_request(be_ctx, be_req, -+ be_ctx->bet_info[BET_ID].bet_ops->handler); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("Failed to file request")); -+ return ret; -+ } -+ -+ return EOK; -+} -+ -+static errno_t - split_name_extended(TALLOC_CTX *mem_ctx, - const char *filter, - char **name, -@@ -742,6 +770,110 @@ split_name_extended(TALLOC_CTX *mem_ctx, - return EOK; - } - -+static void -+be_get_account_info_done(struct be_req *be_req, -+ int dp_err, int dp_ret, -+ const char *errstr); -+ -+struct be_get_account_info_state { -+ int err_maj; -+ int err_min; -+ const char *err_msg; -+}; -+ -+struct tevent_req * -+be_get_account_info_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct be_client *becli, -+ struct be_ctx *be_ctx, -+ struct be_acct_req *ar) -+{ -+ struct tevent_req *req; -+ struct be_get_account_info_state *state; -+ struct be_req *be_req; -+ errno_t ret; -+ -+ req = tevent_req_create(mem_ctx, &state, -+ struct be_get_account_info_state); -+ if (!req) return NULL; -+ -+ be_req = talloc_zero(mem_ctx, struct be_req); -+ if (be_req == NULL) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ be_req->becli = becli; -+ be_req->be_ctx = be_ctx; -+ be_req->fn = be_get_account_info_done; -+ be_req->pvt = req; -+ -+ ret = be_file_account_request(be_req, ar); -+ if (ret != EOK) { -+ goto done; -+ } -+ -+ return req; -+ -+done: -+ tevent_req_error(req, ret); -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void -+be_get_account_info_done(struct be_req *be_req, -+ int dp_err, int dp_ret, -+ const char *errstr) -+{ -+ struct tevent_req *req; -+ struct be_get_account_info_state *state; -+ -+ req = talloc_get_type(be_req->pvt, struct tevent_req); -+ state = tevent_req_data(req, struct be_get_account_info_state); -+ -+ state->err_maj = dp_err; -+ state->err_min = dp_ret; -+ if (errstr) { -+ state->err_msg = talloc_strdup(state, errstr); -+ if (state->err_msg == NULL) { -+ talloc_free(be_req); -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ } -+ -+ talloc_free(be_req); -+ tevent_req_done(req); -+} -+ -+errno_t be_get_account_info_recv(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ int *_err_maj, -+ int *_err_min, -+ const char **_err_msg) -+{ -+ struct be_get_account_info_state *state; -+ -+ state = tevent_req_data(req, struct be_get_account_info_state); -+ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ -+ if (_err_maj) { -+ *_err_maj = state->err_maj; -+ } -+ -+ if (_err_min) { -+ *_err_min = state->err_min; -+ } -+ -+ if (_err_msg) { -+ *_err_msg = talloc_steal(mem_ctx, state->err_msg); -+ } -+ -+ return EOK; -+} -+ - static int be_get_account_info(DBusMessage *message, struct sbus_connection *conn) - { - struct be_acct_req *req; -@@ -845,8 +977,6 @@ static int be_get_account_info(DBusMessage *message, struct sbus_connection *con - goto done; - } - -- be_req->req_data = req; -- - if ((attr_type != BE_ATTR_CORE) && - (attr_type != BE_ATTR_MEM) && - (attr_type != BE_ATTR_ALL)) { -@@ -893,26 +1023,11 @@ static int be_get_account_info(DBusMessage *message, struct sbus_connection *con - goto done; - } - -- /* see if we need a pre request call, only done for initgroups for now */ -- if ((type & 0xFF) == BE_REQ_INITGROUPS) { -- ret = be_initgroups_prereq(be_req); -- if (ret) { -- err_maj = DP_ERR_FATAL; -- err_min = ret; -- err_msg = "Prerequest failed"; -- goto done; -- } -- } -- -- /* process request */ -- -- ret = be_file_request(becli->bectx->bet_info[BET_ID].pvt_bet_data, -- be_req, -- becli->bectx->bet_info[BET_ID].bet_ops->handler); -+ ret = be_file_account_request(be_req, req); - if (ret != EOK) { - err_maj = DP_ERR_FATAL; - err_min = ret; -- err_msg = "Failed to file request"; -+ err_msg = "Cannot file account request"; - goto done; - } - -diff --git a/src/providers/dp_backend.h b/src/providers/dp_backend.h -index 58a9b74..743b6f4 100644 ---- a/src/providers/dp_backend.h -+++ b/src/providers/dp_backend.h -@@ -258,4 +258,19 @@ int be_fo_run_callbacks_at_next_request(struct be_ctx *ctx, - const char *service_name); - - void reset_fo(struct be_ctx *be_ctx); -+ -+/* Request account information */ -+struct tevent_req * -+be_get_account_info_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct be_client *becli, -+ struct be_ctx *be_ctx, -+ struct be_acct_req *ar); -+ -+errno_t be_get_account_info_recv(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ int *_err_maj, -+ int *_err_min, -+ const char **_err_msg); -+ - #endif /* __DP_BACKEND_H___ */ --- -1.8.1.4 - diff --git a/Resolve-GIDs-in-the-simple-access-provider.patch b/Resolve-GIDs-in-the-simple-access-provider.patch deleted file mode 100644 index 91e09a4..0000000 --- a/Resolve-GIDs-in-the-simple-access-provider.patch +++ /dev/null @@ -1,1624 +0,0 @@ -From ba1193c7b950a3849e04e28e60d83eece5ee49bc Mon Sep 17 00:00:00 2001 -From: Jakub Hrozek -Date: Sat, 23 Feb 2013 10:44:54 +0100 -Subject: Resolve GIDs in the simple access provider - -Changes the simple access provider's interface to be asynchronous. When -the simple access provider encounters a group that has gid, but no -meaningful name, it attempts to resolve the name using the -be_file_account_request function. - -Some providers (like the AD provider) might perform initgroups -without resolving the group names. In order for the simple access -provider to work correctly, we need to resolve the groups before -performing the access check. In AD provider, the situation is -even more tricky b/c the groups HAVE name, but their name -attribute is set to SID and they are set as non-POSIX -(cherry picked from commit 8b8019fe3dd1564fba657e219ec20ff816c7ffdb) ---- - Makefile.am | 17 +- - src/providers/simple/simple_access.c | 228 ++------- - src/providers/simple/simple_access.h | 11 +- - src/providers/simple/simple_access_check.c | 723 +++++++++++++++++++++++++++++ - src/tests/simple_access-tests.c | 361 ++++++++++---- - 5 files changed, 1033 insertions(+), 307 deletions(-) - create mode 100644 src/providers/simple/simple_access_check.c - -diff --git a/Makefile.am b/Makefile.am -index dda090d..223431d 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -1008,14 +1008,22 @@ ad_ldap_opt_tests_LDADD = \ - simple_access_tests_SOURCES = \ - src/tests/simple_access-tests.c \ - src/tests/common.c \ -- src/providers/simple/simple_access.c -+ src/providers/simple/simple_access_check.c \ -+ src/providers/data_provider_be.c \ -+ src/providers/data_provider_fo.c \ -+ src/providers/data_provider_callbacks.c \ -+ $(SSSD_FAILOVER_OBJ) - simple_access_tests_CFLAGS = \ - $(AM_CFLAGS) \ -- $(CHECK_CFLAGS) -+ $(CHECK_CFLAGS) \ -+ -DUNIT_TESTING - simple_access_tests_LDADD = \ - $(SSSD_LIBS) \ -+ $(CARES_LIBS) \ - $(CHECK_LIBS) \ -- libsss_util.la -+ $(PAM_LIBS) \ -+ libsss_util.la \ -+ libsss_test_common.la - - util_tests_SOURCES = \ - src/tests/util-tests.c -@@ -1347,7 +1355,8 @@ libsss_proxy_la_LDFLAGS = \ - -module - - libsss_simple_la_SOURCES = \ -- src/providers/simple/simple_access.c -+ src/providers/simple/simple_access.c \ -+ src/providers/simple/simple_access_check.c - libsss_simple_la_CFLAGS = \ - $(AM_CFLAGS) - libsss_simple_la_LIBADD = \ -diff --git a/src/providers/simple/simple_access.c b/src/providers/simple/simple_access.c -index 70d1f07..d53a04b 100644 ---- a/src/providers/simple/simple_access.c -+++ b/src/providers/simple/simple_access.c -@@ -35,227 +35,52 @@ - #define CONFDB_SIMPLE_ALLOW_GROUPS "simple_allow_groups" - #define CONFDB_SIMPLE_DENY_GROUPS "simple_deny_groups" - --errno_t simple_access_check(struct simple_ctx *ctx, const char *username, -- bool *access_granted) --{ -- int i, j; -- errno_t ret; -- TALLOC_CTX *tmp_ctx = NULL; -- const char *user_attrs[] = { SYSDB_MEMBEROF, -- SYSDB_GIDNUM, -- NULL }; -- const char *group_attrs[] = { SYSDB_NAME, -- NULL }; -- struct ldb_message *msg; -- struct ldb_message_element *el; -- char **groups; -- const char *primary_group; -- gid_t gid; -- bool matched; -- bool cs = ctx->domain->case_sensitive; -- -- *access_granted = false; -- -- /* First, check whether the user is in the allowed users list */ -- if (ctx->allow_users != NULL) { -- for(i = 0; ctx->allow_users[i] != NULL; i++) { -- if (sss_string_equal(cs, username, ctx->allow_users[i])) { -- DEBUG(9, ("User [%s] found in allow list, access granted.\n", -- username)); -- -- /* Do not return immediately on explicit allow -- * We need to make sure none of the user's groups -- * are denied. -- */ -- *access_granted = true; -- } -- } -- } else if (!ctx->allow_groups) { -- /* If neither allow rule is in place, we'll assume allowed -- * unless a deny rule disables us below. -- */ -- *access_granted = true; -- } -+static void simple_access_check(struct tevent_req *req); - -- /* Next check whether this user has been specifically denied */ -- if (ctx->deny_users != NULL) { -- for(i = 0; ctx->deny_users[i] != NULL; i++) { -- if (sss_string_equal(cs, username, ctx->deny_users[i])) { -- DEBUG(9, ("User [%s] found in deny list, access denied.\n", -- username)); -- -- /* Return immediately on explicit denial */ -- *access_granted = false; -- return EOK; -- } -- } -- } -+void simple_access_handler(struct be_req *be_req) -+{ -+ struct be_ctx *be_ctx = be_req->be_ctx; -+ struct pam_data *pd; -+ struct tevent_req *req; -+ struct simple_ctx *ctx; - -- if (!ctx->allow_groups && !ctx->deny_groups) { -- /* There are no group restrictions, so just return -- * here with whatever we've decided. -- */ -- return EOK; -- } -+ pd = talloc_get_type(be_req->req_data, struct pam_data); - -- /* Now get a list of this user's groups and check those against the -- * simple_allow_groups list. -- */ -- tmp_ctx = talloc_new(NULL); -- if (!tmp_ctx) { -- ret = ENOMEM; -- goto done; -- } -+ pd->pam_status = PAM_SYSTEM_ERR; - -- ret = sysdb_search_user_by_name(tmp_ctx, ctx->sysdb, -- username, user_attrs, &msg); -- if (ret != EOK) { -- DEBUG(1, ("Could not look up username [%s]: [%d][%s]\n", -- username, ret, strerror(ret))); -+ if (pd->cmd != SSS_PAM_ACCT_MGMT) { -+ DEBUG(4, ("simple access does not handles pam task %d.\n", pd->cmd)); -+ pd->pam_status = PAM_MODULE_UNKNOWN; - goto done; - } - -- /* Construct a list of the user's groups */ -- el = ldb_msg_find_element(msg, SYSDB_MEMBEROF); -- if (el && el->num_values) { -- /* Get the groups from the memberOf entries -- * Allocate the array with room for both the NULL -- * terminator and the primary group -- */ -- groups = talloc_array(tmp_ctx, char *, el->num_values + 2); -- if (!groups) { -- ret = ENOMEM; -- goto done; -- } -- -- for (j = 0; j < el->num_values; j++) { -- ret = sysdb_group_dn_name( -- ctx->sysdb, tmp_ctx, -- (char *)el->values[j].data, -- &groups[j]); -- if (ret != EOK) { -- goto done; -- } -- } -- } else { -- /* User is not a member of any groups except primary */ -- groups = talloc_array(tmp_ctx, char *, 2); -- if (!groups) { -- ret = ENOMEM; -- goto done; -- } -- j = 0; -- } -+ ctx = talloc_get_type(be_req->be_ctx->bet_info[BET_ACCESS].pvt_bet_data, -+ struct simple_ctx); - -- /* Get the user's primary group */ -- gid = ldb_msg_find_attr_as_uint64(msg, SYSDB_GIDNUM, 0); -- if (!gid) { -- ret = EINVAL; -+ req = simple_access_check_send(be_req, be_ctx->ev, ctx, pd->user); -+ if (!req) { -+ pd->pam_status = PAM_SYSTEM_ERR; - goto done; - } -- talloc_zfree(msg); -- -- ret = sysdb_search_group_by_gid(tmp_ctx, ctx->sysdb, -- gid, group_attrs, &msg); -- if (ret != EOK) { -- DEBUG(1, ("Could not look up primary group [%lu]: [%d][%s]\n", -- gid, ret, strerror(ret))); -- /* We have to treat this as non-fatal, because the primary -- * group may be local to the machine and not available in -- * our ID provider. -- */ -- } else { -- primary_group = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL); -- if (!primary_group) { -- ret = EINVAL; -- goto done; -- } -- -- groups[j] = talloc_strdup(tmp_ctx, primary_group); -- if (!groups[j]) { -- ret = ENOMEM; -- goto done; -- } -- j++; -- -- talloc_zfree(msg); -- } -- -- groups[j] = NULL; -- -- /* Now process allow and deny group rules -- * If access was already granted above, we'll skip -- * this redundant rule check -- */ -- if (ctx->allow_groups && !*access_granted) { -- matched = false; -- for (i = 0; ctx->allow_groups[i]; i++) { -- for(j = 0; groups[j]; j++) { -- if (sss_string_equal(cs, groups[j], ctx->allow_groups[i])) { -- matched = true; -- break; -- } -- } -- -- /* If any group has matched, we can skip out on the -- * processing early -- */ -- if (matched) { -- *access_granted = true; -- break; -- } -- } -- } -- -- /* Finally, process the deny group rules */ -- if (ctx->deny_groups) { -- matched = false; -- for (i = 0; ctx->deny_groups[i]; i++) { -- for(j = 0; groups[j]; j++) { -- if (sss_string_equal(cs, groups[j], ctx->deny_groups[i])) { -- matched = true; -- break; -- } -- } -- -- /* If any group has matched, we can skip out on the -- * processing early -- */ -- if (matched) { -- *access_granted = false; -- break; -- } -- } -- } -- -- ret = EOK; -+ tevent_req_set_callback(req, simple_access_check, be_req); -+ return; - - done: -- talloc_free(tmp_ctx); -- return ret; -+ be_req->fn(be_req, DP_ERR_OK, pd->pam_status, NULL); - } - --void simple_access_handler(struct be_req *be_req) -+static void simple_access_check(struct tevent_req *req) - { -- int ret; - bool access_granted = false; -+ errno_t ret; - struct pam_data *pd; -- struct simple_ctx *ctx; -+ struct be_req *be_req; - -+ be_req = tevent_req_callback_data(req, struct be_req); - pd = talloc_get_type(be_req->req_data, struct pam_data); - -- pd->pam_status = PAM_SYSTEM_ERR; -- -- if (pd->cmd != SSS_PAM_ACCT_MGMT) { -- DEBUG(4, ("simple access does not handles pam task %d.\n", pd->cmd)); -- pd->pam_status = PAM_MODULE_UNKNOWN; -- goto done; -- } -- -- ctx = talloc_get_type(be_req->be_ctx->bet_info[BET_ACCESS].pvt_bet_data, -- struct simple_ctx); -- -- ret = simple_access_check(ctx, pd->user, &access_granted); -+ ret = simple_access_check_recv(req, &access_granted); -+ talloc_free(req); - if (ret != EOK) { - pd->pam_status = PAM_SYSTEM_ERR; - goto done; -@@ -290,6 +115,7 @@ int sssm_simple_access_init(struct be_ctx *bectx, struct bet_ops **ops, - - ctx->sysdb = bectx->sysdb; - ctx->domain = bectx->domain; -+ ctx->be_ctx = bectx; - - /* Users */ - ret = confdb_get_string_as_list(bectx->cdb, ctx, bectx->conf_path, -diff --git a/src/providers/simple/simple_access.h b/src/providers/simple/simple_access.h -index abcf61a..1de9d89 100644 ---- a/src/providers/simple/simple_access.h -+++ b/src/providers/simple/simple_access.h -@@ -29,6 +29,7 @@ - struct simple_ctx { - struct sysdb_ctx *sysdb; - struct sss_domain_info *domain; -+ struct be_ctx *be_ctx; - - char **allow_users; - char **deny_users; -@@ -36,6 +37,12 @@ struct simple_ctx { - char **deny_groups; - }; - --errno_t simple_access_check(struct simple_ctx *ctx, const char *username, -- bool *access_granted); -+struct tevent_req *simple_access_check_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct simple_ctx *ctx, -+ const char *username); -+ -+errno_t simple_access_check_recv(struct tevent_req *req, -+ bool *access_granted); -+ - #endif /* __SIMPLE_ACCESS_H__ */ -diff --git a/src/providers/simple/simple_access_check.c b/src/providers/simple/simple_access_check.c -new file mode 100644 -index 0000000..a9e8f63 ---- /dev/null -+++ b/src/providers/simple/simple_access_check.c -@@ -0,0 +1,723 @@ -+/* -+ SSSD -+ -+ Simple access control -+ -+ Copyright (C) Sumit Bose 2010 -+ -+ 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 "providers/dp_backend.h" -+#include "providers/simple/simple_access.h" -+#include "util/sss_utf8.h" -+#include "db/sysdb.h" -+ -+static bool -+is_posix(const struct ldb_message *group) -+{ -+ const char *val; -+ -+ val = ldb_msg_find_attr_as_string(group, SYSDB_POSIX, NULL); -+ if (!val || /* Groups are posix by default */ -+ strcasecmp(val, "TRUE") == 0) { -+ return true; -+ } -+ -+ return false; -+} -+ -+/* Returns EOK if the result is definitive, EAGAIN if only partial result -+ */ -+static errno_t -+simple_check_users(struct simple_ctx *ctx, const char *username, -+ bool *access_granted) -+{ -+ int i; -+ bool cs = ctx->domain->case_sensitive; -+ -+ /* First, check whether the user is in the allowed users list */ -+ if (ctx->allow_users != NULL) { -+ for(i = 0; ctx->allow_users[i] != NULL; i++) { -+ if (sss_string_equal(cs, username, ctx->allow_users[i])) { -+ DEBUG(SSSDBG_TRACE_LIBS, -+ ("User [%s] found in allow list, access granted.\n", -+ username)); -+ -+ /* Do not return immediately on explicit allow -+ * We need to make sure none of the user's groups -+ * are denied. -+ */ -+ *access_granted = true; -+ } -+ } -+ } else if (!ctx->allow_groups) { -+ /* If neither allow rule is in place, we'll assume allowed -+ * unless a deny rule disables us below. -+ */ -+ DEBUG(SSSDBG_TRACE_LIBS, -+ ("No allow rule, assumuing allow unless explicitly denied\n")); -+ *access_granted = true; -+ } -+ -+ /* Next check whether this user has been specifically denied */ -+ if (ctx->deny_users != NULL) { -+ for(i = 0; ctx->deny_users[i] != NULL; i++) { -+ if (sss_string_equal(cs, username, ctx->deny_users[i])) { -+ DEBUG(SSSDBG_TRACE_LIBS, -+ ("User [%s] found in deny list, access denied.\n", -+ username)); -+ -+ /* Return immediately on explicit denial */ -+ *access_granted = false; -+ return EOK; -+ } -+ } -+ } -+ -+ return EAGAIN; -+} -+ -+static errno_t -+simple_check_groups(struct simple_ctx *ctx, const char *username, -+ const char **group_names, bool *access_granted) -+{ -+ bool matched; -+ int i, j; -+ bool cs = ctx->domain->case_sensitive; -+ -+ /* Now process allow and deny group rules -+ * If access was already granted above, we'll skip -+ * this redundant rule check -+ */ -+ if (ctx->allow_groups && !*access_granted) { -+ matched = false; -+ for (i = 0; ctx->allow_groups[i]; i++) { -+ for(j = 0; group_names[j]; j++) { -+ if (sss_string_equal(cs, group_names[j], ctx->allow_groups[i])) { -+ matched = true; -+ break; -+ } -+ } -+ -+ /* If any group has matched, we can skip out on the -+ * processing early -+ */ -+ if (matched) { -+ DEBUG(SSSDBG_TRACE_LIBS, -+ ("Group [%s] found in allow list, access granted.\n", -+ group_names[j])); -+ *access_granted = true; -+ break; -+ } -+ } -+ } -+ -+ /* Finally, process the deny group rules */ -+ if (ctx->deny_groups) { -+ matched = false; -+ for (i = 0; ctx->deny_groups[i]; i++) { -+ for(j = 0; group_names[j]; j++) { -+ if (sss_string_equal(cs, group_names[j], ctx->deny_groups[i])) { -+ matched = true; -+ break; -+ } -+ } -+ -+ /* If any group has matched, we can skip out on the -+ * processing early -+ */ -+ if (matched) { -+ DEBUG(SSSDBG_TRACE_LIBS, -+ ("Group [%s] found in deny list, access denied.\n", -+ group_names[j])); -+ *access_granted = false; -+ break; -+ } -+ } -+ } -+ -+ return EOK; -+} -+ -+struct simple_resolve_group_state { -+ gid_t gid; -+ struct simple_ctx *ctx; -+ -+ const char *name; -+}; -+ -+static errno_t -+simple_resolve_group_check(struct simple_resolve_group_state *state); -+static void simple_resolve_group_done(struct tevent_req *subreq); -+ -+static struct tevent_req * -+simple_resolve_group_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct simple_ctx *ctx, -+ gid_t gid) -+{ -+ errno_t ret; -+ struct tevent_req *req; -+ struct tevent_req *subreq; -+ struct simple_resolve_group_state *state; -+ struct be_acct_req *ar; -+ -+ req = tevent_req_create(mem_ctx, &state, -+ struct simple_resolve_group_state); -+ if (!req) return NULL; -+ -+ state->gid = gid; -+ state->ctx = ctx; -+ -+ /* First check if the group was updated already. If it was (maybe its -+ * parent was updated first), then just shortcut */ -+ ret = simple_resolve_group_check(state); -+ if (ret == EOK) { -+ DEBUG(SSSDBG_TRACE_LIBS, ("Group already updated\n")); -+ ret = EOK; -+ goto done; -+ } else if (ret != EAGAIN) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ ("Cannot check if group was already updated\n")); -+ goto done; -+ } -+ /* EAGAIN - still needs update */ -+ -+ ar = talloc(state, struct be_acct_req); -+ if (!ar) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ ar->entry_type = BE_REQ_GROUP; -+ ar->attr_type = BE_ATTR_CORE; -+ ar->filter_type = BE_FILTER_IDNUM; -+ ar->filter_value = talloc_asprintf(ar, "%llu", (unsigned long long) gid); -+ ar->domain = talloc_strdup(ar, ctx->domain->name); -+ if (!ar->domain || !ar->filter_value) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ subreq = be_get_account_info_send(state, ev, NULL, ctx->be_ctx, ar); -+ if (!subreq) { -+ ret = ENOMEM; -+ goto done; -+ } -+ tevent_req_set_callback(subreq, simple_resolve_group_done, req); -+ -+ return req; -+ -+done: -+ if (ret == EOK) { -+ tevent_req_done(req); -+ } else { -+ tevent_req_error(req, ret); -+ } -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static errno_t -+simple_resolve_group_check(struct simple_resolve_group_state *state) -+{ -+ errno_t ret; -+ struct ldb_message *group; -+ const char *group_attrs[] = { SYSDB_NAME, SYSDB_POSIX, -+ SYSDB_GIDNUM, NULL }; -+ -+ /* Check the cache by GID again and fetch the name */ -+ ret = sysdb_search_group_by_gid(state, state->ctx->domain->sysdb, -+ state->gid, group_attrs, &group); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ ("Could not look up group by gid [%lu]: [%d][%s]\n", -+ state->gid, ret, strerror(ret))); -+ return ret; -+ } -+ -+ state->name = ldb_msg_find_attr_as_string(group, SYSDB_NAME, NULL); -+ if (!state->name) { -+ DEBUG(SSSDBG_OP_FAILURE, ("No group name\n")); -+ return ENOENT; -+ } -+ -+ if (is_posix(group) == false) { -+ DEBUG(SSSDBG_TRACE_LIBS, -+ ("The group is still non-POSIX\n")); -+ return EAGAIN; -+ } -+ -+ DEBUG(SSSDBG_TRACE_LIBS, ("Got POSIX group\n")); -+ return EOK; -+} -+ -+static void simple_resolve_group_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req; -+ struct simple_resolve_group_state *state; -+ int err_maj; -+ int err_min; -+ errno_t ret; -+ const char *err_msg; -+ -+ req = tevent_req_callback_data(subreq, struct tevent_req); -+ state = tevent_req_data(req, struct simple_resolve_group_state); -+ -+ ret = be_get_account_info_recv(subreq, state, -+ &err_maj, &err_min, &err_msg); -+ talloc_zfree(subreq); -+ if (ret) { -+ DEBUG(SSSDBG_OP_FAILURE, ("be_get_account_info_recv failed\n")); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ if (err_maj) { -+ DEBUG(SSSDBG_MINOR_FAILURE, -+ ("Cannot refresh data from DP: %u,%u: %s\n", -+ err_maj, err_min, err_msg)); -+ tevent_req_error(req, EIO); -+ return; -+ } -+ -+ /* Check the cache by GID again and fetch the name */ -+ ret = simple_resolve_group_check(state); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, ("Refresh failed\n")); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ tevent_req_done(req); -+} -+ -+static errno_t -+simple_resolve_group_recv(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ const char **name) -+{ -+ struct simple_resolve_group_state *state; -+ -+ state = tevent_req_data(req, struct simple_resolve_group_state); -+ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ -+ *name = talloc_strdup(mem_ctx, state->name); -+ return EOK; -+} -+ -+struct simple_check_groups_state { -+ struct tevent_context *ev; -+ struct simple_ctx *ctx; -+ -+ gid_t *lookup_gids; -+ size_t num_gids; -+ size_t giter; -+ -+ const char **group_names; -+ size_t num_names; -+}; -+ -+static void simple_check_get_groups_next(struct tevent_req *subreq); -+ -+static errno_t -+simple_check_get_groups_primary(struct simple_check_groups_state *state, -+ gid_t gid); -+static errno_t -+simple_check_process_group(struct simple_check_groups_state *state, -+ struct ldb_message *group); -+ -+static struct tevent_req * -+simple_check_get_groups_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct simple_ctx *ctx, -+ const char *username) -+{ -+ errno_t ret; -+ struct tevent_req *req; -+ struct tevent_req *subreq; -+ struct simple_check_groups_state *state; -+ const char *attrs[] = { SYSDB_NAME, SYSDB_POSIX, SYSDB_GIDNUM, NULL }; -+ size_t group_count; -+ struct ldb_message *user; -+ struct ldb_message **groups; -+ int i; -+ gid_t gid; -+ char *cname; -+ -+ req = tevent_req_create(mem_ctx, &state, -+ struct simple_check_groups_state); -+ if (!req) return NULL; -+ -+ state->ev = ev; -+ state->ctx = ctx; -+ -+ cname = sss_get_cased_name(state, username, ctx->domain->case_sensitive); -+ if (!cname) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ DEBUG(SSSDBG_TRACE_LIBS, ("Looking up groups for user %s\n", cname)); -+ -+ ret = sysdb_search_user_by_name(state, ctx->domain->sysdb, -+ cname, attrs, &user); -+ if (ret == ENOENT) { -+ DEBUG(SSSDBG_MINOR_FAILURE, ("No such user %s\n", cname)); -+ goto done; -+ } else if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ ("Could not look up username [%s]: [%d][%s]\n", -+ username, ret, strerror(ret))); -+ goto done; -+ } -+ -+ ret = sysdb_asq_search(state, ctx->domain->sysdb, -+ user->dn, NULL, SYSDB_MEMBEROF, -+ attrs, &group_count, &groups); -+ if (ret != EOK) { -+ goto done; -+ } -+ -+ DEBUG(SSSDBG_TRACE_FUNC, -+ ("User %s is a member of %d supplemental groups\n", -+ cname, group_count)); -+ -+ /* One extra space for terminator, one extra space for private group */ -+ state->group_names = talloc_zero_array(state, const char *, group_count + 2); -+ state->lookup_gids = talloc_zero_array(state, gid_t, group_count + 2); -+ if (!state->group_names || !state->lookup_gids) { -+ ret = ENOMEM; -+ goto done; -+ } -+ -+ for (i=0; i < group_count; i++) { -+ /* Some providers (like the AD provider) might perform initgroups -+ * without resolving the group names. In order for the simple access -+ * provider to work correctly, we need to resolve the groups before -+ * performing the access check. In AD provider, the situation is -+ * even more tricky b/c the groups HAVE name, but their name -+ * attribute is set to SID and they are set as non-POSIX -+ */ -+ ret = simple_check_process_group(state, groups[i]); -+ if (ret != EOK) { -+ goto done; -+ } -+ } -+ -+ gid = ldb_msg_find_attr_as_uint64(user, SYSDB_GIDNUM, 0); -+ if (!gid) { -+ DEBUG(SSSDBG_MINOR_FAILURE, ("User %s has no gid?\n", cname)); -+ ret = EINVAL; -+ goto done; -+ } -+ -+ ret = simple_check_get_groups_primary(state, gid); -+ if (ret != EOK) { -+ goto done; -+ } -+ -+ if (state->num_gids == 0) { -+ /* If all groups could have been resolved by name, we are -+ * done -+ */ -+ DEBUG(SSSDBG_TRACE_FUNC, ("All groups had name attribute\n")); -+ ret = EOK; -+ goto done; -+ } -+ -+ DEBUG(SSSDBG_TRACE_FUNC, ("Need to resolve %d groups\n", state->num_gids)); -+ state->giter = 0; -+ subreq = simple_resolve_group_send(req, state->ev, state->ctx, -+ state->lookup_gids[state->giter]); -+ if (!subreq) { -+ ret = ENOMEM; -+ goto done; -+ } -+ tevent_req_set_callback(subreq, simple_check_get_groups_next, req); -+ -+ return req; -+ -+done: -+ if (ret == EOK) { -+ tevent_req_done(req); -+ } else { -+ tevent_req_error(req, ret); -+ } -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+static void simple_check_get_groups_next(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = -+ tevent_req_callback_data(subreq, struct tevent_req); -+ struct simple_check_groups_state *state = -+ tevent_req_data(req, struct simple_check_groups_state); -+ errno_t ret; -+ -+ ret = simple_resolve_group_recv(subreq, state->group_names, -+ &state->group_names[state->num_names]); -+ talloc_zfree(subreq); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ ("Could not resolve name of group with GID %llu\n", -+ state->lookup_gids[state->giter])); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ state->num_names++; -+ state->giter++; -+ -+ if (state->giter < state->num_gids) { -+ subreq = simple_resolve_group_send(req, state->ev, state->ctx, -+ state->lookup_gids[state->giter]); -+ if (!subreq) { -+ tevent_req_error(req, ENOMEM); -+ return; -+ } -+ tevent_req_set_callback(subreq, simple_check_get_groups_next, req); -+ return; -+ } -+ -+ DEBUG(SSSDBG_TRACE_INTERNAL, ("All groups resolved. Done.\n")); -+ tevent_req_done(req); -+} -+ -+static errno_t -+simple_check_process_group(struct simple_check_groups_state *state, -+ struct ldb_message *group) -+{ -+ const char *name; -+ gid_t gid; -+ bool posix; -+ -+ posix = is_posix(group); -+ name = ldb_msg_find_attr_as_string(group, SYSDB_NAME, NULL); -+ gid = ldb_msg_find_attr_as_uint64(group, SYSDB_GIDNUM, 0); -+ -+ /* With the current sysdb layout, every group has a name */ -+ if (name == NULL) { -+ return EINVAL; -+ } -+ -+ if (gid == 0) { -+ if (posix == true) { -+ DEBUG(SSSDBG_CRIT_FAILURE, ("POSIX group without GID\n")); -+ return EINVAL; -+ } -+ -+ /* Non-posix group with a name. Still can be used for access -+ * control as the name should point to the real name, no SID -+ */ -+ state->group_names[state->num_names] = talloc_strdup(state->group_names, -+ name); -+ if (!state->group_names[state->num_names]) { -+ return ENOMEM; -+ } -+ DEBUG(SSSDBG_TRACE_INTERNAL, ("Adding group %s\n", name)); -+ state->num_names++; -+ return EOK; -+ } -+ -+ /* Here are only groups with a name and gid. POSIX group can already -+ * be used, non-POSIX groups can be resolved */ -+ if (posix) { -+ state->group_names[state->num_names] = talloc_strdup(state->group_names, -+ name); -+ if (!state->group_names[state->num_names]) { -+ return ENOMEM; -+ } -+ DEBUG(SSSDBG_TRACE_INTERNAL, ("Adding group %s\n", name)); -+ state->num_names++; -+ return EOK; -+ } -+ -+ /* Non-posix group with a GID. Needs resolving */ -+ state->lookup_gids[state->num_gids] = gid; -+ DEBUG(SSSDBG_TRACE_INTERNAL, ("Adding GID %llu\n", gid)); -+ state->num_gids++; -+ return EOK; -+} -+ -+static errno_t -+simple_check_get_groups_primary(struct simple_check_groups_state *state, -+ gid_t gid) -+{ -+ errno_t ret; -+ const char *group_attrs[] = { SYSDB_NAME, SYSDB_POSIX, -+ SYSDB_GIDNUM, NULL }; -+ struct ldb_message *msg; -+ -+ ret = sysdb_search_group_by_gid(state, state->ctx->domain->sysdb, -+ gid, group_attrs, &msg); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ ("Could not look up primary group [%lu]: [%d][%s]\n", -+ gid, ret, strerror(ret))); -+ /* We have to treat this as non-fatal, because the primary -+ * group may be local to the machine and not available in -+ * our ID provider. -+ */ -+ } else { -+ ret = simple_check_process_group(state, msg); -+ if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, ("Cannot process primary group\n")); -+ return ret; -+ } -+ } -+ -+ return EOK; -+} -+ -+static errno_t -+simple_check_get_groups_recv(struct tevent_req *req, -+ TALLOC_CTX *mem_ctx, -+ const char ***_group_names) -+{ -+ struct simple_check_groups_state *state; -+ -+ state = tevent_req_data(req, struct simple_check_groups_state); -+ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ -+ *_group_names = talloc_steal(mem_ctx, state->group_names); -+ return EOK; -+} -+ -+struct simple_access_check_state { -+ bool access_granted; -+ struct simple_ctx *ctx; -+ const char *username; -+ -+ const char **group_names; -+}; -+ -+static void simple_access_check_done(struct tevent_req *subreq); -+ -+struct tevent_req *simple_access_check_send(TALLOC_CTX *mem_ctx, -+ struct tevent_context *ev, -+ struct simple_ctx *ctx, -+ const char *username) -+{ -+ errno_t ret; -+ struct tevent_req *req; -+ struct tevent_req *subreq; -+ struct simple_access_check_state *state; -+ -+ req = tevent_req_create(mem_ctx, &state, -+ struct simple_access_check_state); -+ if (!req) return NULL; -+ -+ state->access_granted = false; -+ state->ctx = ctx; -+ state->username = talloc_strdup(state, username); -+ if (!state->username) { -+ ret = ENOMEM; -+ goto immediate; -+ } -+ -+ DEBUG(SSSDBG_FUNC_DATA, ("Simple access check for %s\n", username)); -+ -+ ret = simple_check_users(ctx, username, &state->access_granted); -+ if (ret != EAGAIN) { -+ /* Both access denied and an error */ -+ goto immediate; -+ } -+ -+ if (!ctx->allow_groups && !ctx->deny_groups) { -+ /* There are no group restrictions, so just return -+ * here with whatever we've decided. -+ */ -+ DEBUG(SSSDBG_TRACE_LIBS, ("No group restrictions, end request\n")); -+ ret = EOK; -+ goto immediate; -+ } -+ -+ /* The group names might not be available. Fire a request to -+ * gather them. In most cases, the request will just shortcut -+ */ -+ subreq = simple_check_get_groups_send(state, ev, ctx, username); -+ if (!subreq) { -+ ret = EIO; -+ goto immediate; -+ } -+ tevent_req_set_callback(subreq, simple_access_check_done, req); -+ -+ return req; -+ -+immediate: -+ if (ret == EOK) { -+ tevent_req_done(req); -+ } else { -+ tevent_req_error(req, ret); -+ } -+ tevent_req_post(req, ev); -+ return req; -+} -+ -+ -+static void simple_access_check_done(struct tevent_req *subreq) -+{ -+ struct tevent_req *req = -+ tevent_req_callback_data(subreq, struct tevent_req); -+ struct simple_access_check_state *state = -+ tevent_req_data(req, struct simple_access_check_state); -+ errno_t ret; -+ -+ /* We know the names now. Run the check. */ -+ ret = simple_check_get_groups_recv(subreq, state, &state->group_names); -+ talloc_zfree(subreq); -+ if (ret == ENOENT) { -+ /* If the user wasn't found, just shortcut */ -+ state->access_granted = false; -+ tevent_req_done(req); -+ return; -+ } else if (ret != EOK) { -+ DEBUG(SSSDBG_OP_FAILURE, -+ ("Could not collect groups of user %s\n", state->username)); -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ ret = simple_check_groups(state->ctx, state->username, -+ state->group_names, &state->access_granted); -+ if (ret != EOK) { -+ tevent_req_error(req, ret); -+ return; -+ } -+ -+ /* Now just return whatever we decided */ -+ DEBUG(SSSDBG_TRACE_INTERNAL, ("Group check done\n")); -+ tevent_req_done(req); -+} -+ -+errno_t simple_access_check_recv(struct tevent_req *req, bool *access_granted) -+{ -+ struct simple_access_check_state *state = -+ tevent_req_data(req, struct simple_access_check_state); -+ -+ TEVENT_REQ_RETURN_ON_ERROR(req); -+ -+ DEBUG(SSSDBG_TRACE_LIBS, -+ ("Access %sgranted\n", state->access_granted ? "" : "not ")); -+ if (access_granted) { -+ *access_granted = state->access_granted; -+ } -+ -+ return EOK; -+} -diff --git a/src/tests/simple_access-tests.c b/src/tests/simple_access-tests.c -index 577c6d3..ab2612d 100644 ---- a/src/tests/simple_access-tests.c -+++ b/src/tests/simple_access-tests.c -@@ -27,6 +27,7 @@ - #include - - #include "confdb/confdb.h" -+#include "db/sysdb_private.h" - #include "providers/simple/simple_access.h" - #include "tests/common.h" - -@@ -35,16 +36,40 @@ - - const char *ulist_1[] = {"u1", "u2", NULL}; - const char *glist_1[] = {"g1", "g2", NULL}; -+const char *glist_1_case[] = {"G1", "G2", NULL}; - - struct simple_test_ctx *test_ctx = NULL; - - struct simple_test_ctx { - struct sysdb_ctx *sysdb; - struct confdb_ctx *confdb; -+ struct tevent_context *ev; -+ bool done; -+ int error; - -+ bool access_granted; - struct simple_ctx *ctx; - }; - -+static int test_loop(struct simple_test_ctx *tctx) -+{ -+ while (!tctx->done) -+ tevent_loop_once(tctx->ev); -+ -+ return tctx->error; -+} -+ -+static void simple_access_check_done(struct tevent_req *req) -+{ -+ struct simple_test_ctx *tctx = -+ tevent_req_callback_data(req, struct simple_test_ctx); -+ -+ -+ tctx->error = simple_access_check_recv(req, &tctx->access_granted); -+ talloc_free(req); -+ tctx->done = true; -+} -+ - void setup_simple(void) - { - errno_t ret; -@@ -52,19 +77,22 @@ void setup_simple(void) - const char *val[2]; - val[1] = NULL; - -- /* Create tests directory if it doesn't exist */ -- /* (relative to current dir) */ -- ret = mkdir(TESTS_PATH, 0775); -- fail_if(ret == -1 && errno != EEXIST, -- "Could not create %s directory", TESTS_PATH); -- - fail_unless(test_ctx == NULL, "Simple context already initialized."); - test_ctx = talloc_zero(NULL, struct simple_test_ctx); - fail_unless(test_ctx != NULL, "Cannot create simple test context."); - -+ test_ctx->ev = tevent_context_init(test_ctx); -+ fail_unless(test_ctx->ev != NULL, "Cannot create tevent context."); -+ - test_ctx->ctx = talloc_zero(test_ctx, struct simple_ctx); - fail_unless(test_ctx->ctx != NULL, "Cannot create simple context."); - -+ /* Create tests directory if it doesn't exist */ -+ /* (relative to current dir) */ -+ ret = mkdir(TESTS_PATH, 0775); -+ fail_if(ret == -1 && errno != EEXIST, -+ "Could not create %s directory", TESTS_PATH); -+ - conf_db = talloc_asprintf(test_ctx, "%s/%s", TESTS_PATH, TEST_CONF_FILE); - fail_if(conf_db == NULL, "Out of memory, aborting!"); - DEBUG(SSSDBG_TRACE_LIBS, ("CONFDB: %s\n", conf_db)); -@@ -98,6 +126,7 @@ void setup_simple(void) - &test_ctx->ctx->domain, &test_ctx->ctx->sysdb); - fail_if(ret != EOK, "Could not initialize connection to the sysdb (%d)", ret); - test_ctx->ctx->domain->case_sensitive = true; -+ test_ctx->ctx->sysdb->mpg = false; /* Simulate an LDAP domain better */ - } - - void teardown_simple(void) -@@ -117,18 +146,22 @@ void setup_simple_group(void) - - /* Add test users u1 and u2 that would be members of test groups - * g1 and g2 respectively */ -+ ret = sysdb_add_group(test_ctx->ctx->sysdb, -+ "pvt", 999, NULL, 0, 0); -+ fail_if(ret != EOK, "Could not add private group"); -+ - ret = sysdb_store_user(test_ctx->ctx->sysdb, -- "u1", NULL, 123, 0, "u1", "/home/u1", -+ "u1", NULL, 123, 999, "u1", "/home/u1", - "/bin/bash", NULL, NULL, NULL, -1, 0); - fail_if(ret != EOK, "Could not add u1"); - - ret = sysdb_store_user(test_ctx->ctx->sysdb, -- "u2", NULL, 456, 0, "u1", "/home/u1", -+ "u2", NULL, 456, 999, "u1", "/home/u1", - "/bin/bash", NULL, NULL, NULL, -1, 0); - fail_if(ret != EOK, "Could not add u2"); - - ret = sysdb_store_user(test_ctx->ctx->sysdb, -- "u3", NULL, 789, 0, "u1", "/home/u1", -+ "u3", NULL, 789, 999, "u1", "/home/u1", - "/bin/bash", NULL, NULL, NULL, -1, 0); - fail_if(ret != EOK, "Could not add u3"); - -@@ -163,190 +196,317 @@ void teardown_simple_group(void) - fail_if(ret != EOK, "Could not delete g1"); - ret = sysdb_delete_group(test_ctx->ctx->sysdb, "g2", 0); - fail_if(ret != EOK, "Could not delete g2"); -+ ret = sysdb_delete_group(test_ctx->ctx->sysdb, "pvt", 0); -+ fail_if(ret != EOK, "Could not delete pvt"); - - teardown_simple(); - } - - START_TEST(test_both_empty) - { -- int ret; -- bool access_granted = false; -+ struct tevent_req *req; - - test_ctx->ctx->allow_users = NULL; - test_ctx->ctx->deny_users = NULL; - -- ret = simple_access_check(test_ctx->ctx, "u1", &access_granted); -- fail_unless(ret == EOK, "access_simple_check failed."); -- fail_unless(access_granted == true, "Access denied " -- "while both lists are empty."); -+ req = simple_access_check_send(test_ctx, test_ctx->ev, -+ test_ctx->ctx, "u1"); -+ fail_unless(test_ctx != NULL, "Cannot create request\n"); -+ tevent_req_set_callback(req, simple_access_check_done, test_ctx); -+ -+ test_loop(test_ctx); -+ -+ fail_unless(test_ctx->error == EOK, "access_simple_check failed."); -+ fail_unless(test_ctx->access_granted == true, -+ "Access denied while both lists are empty."); - } - END_TEST - - START_TEST(test_allow_empty) - { -- int ret; -- bool access_granted = true; -+ struct tevent_req *req; - - test_ctx->ctx->allow_users = NULL; - test_ctx->ctx->deny_users = discard_const(ulist_1); - -- ret = simple_access_check(test_ctx->ctx, "u1", &access_granted); -- fail_unless(ret == EOK, "access_simple_check failed."); -- fail_unless(access_granted == false, "Access granted " -- "while user is in deny list."); -+ req = simple_access_check_send(test_ctx, test_ctx->ev, -+ test_ctx->ctx, "u1"); -+ fail_unless(test_ctx != NULL, "Cannot create request\n"); -+ tevent_req_set_callback(req, simple_access_check_done, test_ctx); -+ -+ test_loop(test_ctx); -+ test_ctx->done = false; -+ -+ fail_unless(test_ctx->error == EOK, "access_simple_check failed."); -+ fail_unless(test_ctx->access_granted == false, -+ "Access granted while user is in deny list."); - -- ret = simple_access_check(test_ctx->ctx, "u3", &access_granted); -- fail_unless(ret == EOK, "access_simple_check failed."); -- fail_unless(access_granted == true, "Access denied " -- "while user is not in deny list."); -+ req = simple_access_check_send(test_ctx, test_ctx->ev, -+ test_ctx->ctx, "u3"); -+ fail_unless(test_ctx != NULL, "Cannot create request\n"); -+ tevent_req_set_callback(req, simple_access_check_done, test_ctx); -+ -+ test_loop(test_ctx); -+ -+ fail_unless(test_ctx->error == EOK, "access_simple_check failed."); -+ fail_unless(test_ctx->access_granted == true, -+ "Access denied while user is not in deny list."); - } - END_TEST - - START_TEST(test_deny_empty) - { -- int ret; -- bool access_granted = false; -+ struct tevent_req *req; - - test_ctx->ctx->allow_users = discard_const(ulist_1); - test_ctx->ctx->deny_users = NULL; - -- ret = simple_access_check(test_ctx->ctx, "u1", &access_granted); -- fail_unless(ret == EOK, "access_simple_check failed."); -- fail_unless(access_granted == true, "Access denied " -- "while user is in allow list."); -+ req = simple_access_check_send(test_ctx, test_ctx->ev, -+ test_ctx->ctx, "u1"); -+ fail_unless(test_ctx != NULL, "Cannot create request\n"); -+ tevent_req_set_callback(req, simple_access_check_done, test_ctx); -+ -+ test_loop(test_ctx); -+ test_ctx->done = false; -+ -+ fail_unless(test_ctx->error == EOK, "access_simple_check failed."); -+ fail_unless(test_ctx->access_granted == true, -+ "Access denied while user is in allow list."); - -- ret = simple_access_check(test_ctx->ctx, "u3", &access_granted); -- fail_unless(ret == EOK, "access_simple_check failed."); -- fail_unless(access_granted == false, "Access granted " -- "while user is not in allow list."); -+ req = simple_access_check_send(test_ctx, test_ctx->ev, -+ test_ctx->ctx, "u3"); -+ fail_unless(test_ctx != NULL, "Cannot create request\n"); -+ tevent_req_set_callback(req, simple_access_check_done, test_ctx); -+ -+ test_loop(test_ctx); -+ -+ fail_unless(test_ctx->error == EOK, "access_simple_check failed."); -+ fail_unless(test_ctx->access_granted == false, -+ "Access granted while user is not in allow list."); - } - END_TEST - - START_TEST(test_both_set) - { -- int ret; -- bool access_granted = false; -+ struct tevent_req *req; - - test_ctx->ctx->allow_users = discard_const(ulist_1); - test_ctx->ctx->deny_users = discard_const(ulist_1); - -- ret = simple_access_check(test_ctx->ctx, "u1", &access_granted); -- fail_unless(ret == EOK, "access_simple_check failed."); -- fail_unless(access_granted == false, "Access granted " -- "while user is in deny list."); -+ req = simple_access_check_send(test_ctx, test_ctx->ev, -+ test_ctx->ctx, "u1"); -+ fail_unless(test_ctx != NULL, "Cannot create request\n"); -+ tevent_req_set_callback(req, simple_access_check_done, test_ctx); -+ -+ test_loop(test_ctx); -+ test_ctx->done = false; -+ -+ fail_unless(test_ctx->error == EOK, "access_simple_check failed."); -+ fail_unless(test_ctx->access_granted == false, -+ "Access granted while user is in deny list."); - -- ret = simple_access_check(test_ctx->ctx, "u3", &access_granted); -- fail_unless(ret == EOK, "access_simple_check failed."); -- fail_unless(access_granted == false, "Access granted " -- "while user is not in allow list."); -+ req = simple_access_check_send(test_ctx, test_ctx->ev, -+ test_ctx->ctx, "u3"); -+ fail_unless(test_ctx != NULL, "Cannot create request\n"); -+ tevent_req_set_callback(req, simple_access_check_done, test_ctx); -+ -+ test_loop(test_ctx); -+ -+ fail_unless(test_ctx->error == EOK, "access_simple_check failed."); -+ fail_unless(test_ctx->access_granted == false, -+ "Access granted while user is not in allow list."); - } - END_TEST - - START_TEST(test_case) - { -- int ret; -- bool access_granted = false; -+ struct tevent_req *req; - - test_ctx->ctx->allow_users = discard_const(ulist_1); - test_ctx->ctx->deny_users = NULL; - -- ret = simple_access_check(test_ctx->ctx, "U1", &access_granted); -- fail_unless(ret == EOK, "access_simple_check failed."); -- fail_unless(access_granted == false, "Access granted " -- "for user with different case " -- "in case-sensitive domain"); -+ req = simple_access_check_send(test_ctx, test_ctx->ev, -+ test_ctx->ctx, "U1"); -+ fail_unless(test_ctx != NULL, "Cannot create request\n"); -+ tevent_req_set_callback(req, simple_access_check_done, test_ctx); -+ -+ test_loop(test_ctx); -+ test_ctx->done = false; -+ -+ fail_unless(test_ctx->error == EOK, "access_simple_check failed."); -+ fail_unless(test_ctx->access_granted == false, -+ "Access granted for user with different case " -+ "in case-sensitive domain"); - - test_ctx->ctx->domain->case_sensitive = false; - -- ret = simple_access_check(test_ctx->ctx, "U1", &access_granted); -- fail_unless(ret == EOK, "access_simple_check failed."); -- fail_unless(access_granted == true, "Access denied " -- "for user with different case " -- "in case-insensitive domain"); -+ req = simple_access_check_send(test_ctx, test_ctx->ev, -+ test_ctx->ctx, "U1"); -+ fail_unless(test_ctx != NULL, "Cannot create request\n"); -+ tevent_req_set_callback(req, simple_access_check_done, test_ctx); -+ -+ test_loop(test_ctx); -+ test_ctx->done = false; -+ -+ fail_unless(test_ctx->error == EOK, "access_simple_check failed."); -+ fail_unless(test_ctx->access_granted == true, -+ "Access denied for user with different case " -+ "in case-sensitive domain"); -+} -+END_TEST -+ -+START_TEST(test_unknown_user) -+{ -+ struct tevent_req *req; -+ -+ test_ctx->ctx->allow_users = discard_const(ulist_1); -+ test_ctx->ctx->deny_users = NULL; -+ -+ req = simple_access_check_send(test_ctx, test_ctx->ev, -+ test_ctx->ctx, "foo"); -+ fail_unless(test_ctx != NULL, "Cannot create request\n"); -+ tevent_req_set_callback(req, simple_access_check_done, test_ctx); -+ -+ test_loop(test_ctx); -+ test_ctx->done = false; -+ -+ fail_unless(test_ctx->error == EOK, "access_simple_check failed."); -+ fail_unless(test_ctx->access_granted == false, -+ "Access granted for user not present in domain"); - } - END_TEST - -+ - START_TEST(test_group_allow_empty) - { -- int ret; -- bool access_granted = true; -+ struct tevent_req *req; - - test_ctx->ctx->allow_groups = NULL; - test_ctx->ctx->deny_groups = discard_const(glist_1); - -- ret = simple_access_check(test_ctx->ctx, "u1", &access_granted); -- fail_unless(ret == EOK, "access_simple_check failed."); -- fail_unless(access_granted == false, "Access granted " -- "while group is in deny list."); -+ req = simple_access_check_send(test_ctx, test_ctx->ev, -+ test_ctx->ctx, "u1"); -+ fail_unless(test_ctx != NULL, "Cannot create request\n"); -+ tevent_req_set_callback(req, simple_access_check_done, test_ctx); -+ -+ test_loop(test_ctx); -+ test_ctx->done = false; - -- ret = simple_access_check(test_ctx->ctx, "u3", &access_granted); -- fail_unless(ret == EOK, "access_simple_check failed."); -- fail_unless(access_granted == true, "Access denied " -- "while group is not in deny list."); -+ fail_unless(test_ctx->error == EOK, "access_simple_check failed."); -+ fail_unless(test_ctx->access_granted == false, -+ "Access granted while group is in deny list."); -+ -+ req = simple_access_check_send(test_ctx, test_ctx->ev, -+ test_ctx->ctx, "u3"); -+ fail_unless(test_ctx != NULL, "Cannot create request\n"); -+ tevent_req_set_callback(req, simple_access_check_done, test_ctx); -+ -+ test_loop(test_ctx); -+ -+ fail_unless(test_ctx->error == EOK, "access_simple_check failed."); -+ fail_unless(test_ctx->access_granted == true, -+ "Access denied while group is not in deny list."); - } - END_TEST - - START_TEST(test_group_deny_empty) - { -- int ret; -- bool access_granted = false; -+ struct tevent_req *req; - - test_ctx->ctx->allow_groups = discard_const(glist_1); - test_ctx->ctx->deny_groups = NULL; - -- ret = simple_access_check(test_ctx->ctx, "u1", &access_granted); -- fail_unless(ret == EOK, "access_simple_check failed."); -- fail_unless(access_granted == true, "Access denied " -- "while group is in allow list."); -+ req = simple_access_check_send(test_ctx, test_ctx->ev, -+ test_ctx->ctx, "u1"); -+ fail_unless(test_ctx != NULL, "Cannot create request\n"); -+ tevent_req_set_callback(req, simple_access_check_done, test_ctx); -+ -+ test_loop(test_ctx); -+ test_ctx->done = false; - -- ret = simple_access_check(test_ctx->ctx, "u3", &access_granted); -- fail_unless(ret == EOK, "access_simple_check failed."); -- fail_unless(access_granted == false, "Access granted " -- "while group is not in allow list."); -+ fail_unless(test_ctx->error == EOK, "access_simple_check failed."); -+ fail_unless(test_ctx->access_granted == true, -+ "Access denied while user is in allow list."); -+ -+ req = simple_access_check_send(test_ctx, test_ctx->ev, -+ test_ctx->ctx, "u3"); -+ fail_unless(test_ctx != NULL, "Cannot create request\n"); -+ tevent_req_set_callback(req, simple_access_check_done, test_ctx); -+ -+ test_loop(test_ctx); -+ -+ fail_unless(test_ctx->error == EOK, "access_simple_check failed."); -+ fail_unless(test_ctx->access_granted == false, -+ "Access granted while user is not in allow list."); - } - END_TEST - - START_TEST(test_group_both_set) - { -- int ret; -- bool access_granted = false; -+ struct tevent_req *req; - - test_ctx->ctx->allow_groups = discard_const(ulist_1); - test_ctx->ctx->deny_groups = discard_const(ulist_1); - -- ret = simple_access_check(test_ctx->ctx, "u1", &access_granted); -- fail_unless(ret == EOK, "access_simple_check failed."); -- fail_unless(access_granted == false, "Access granted " -- "while group is in deny list."); -+ req = simple_access_check_send(test_ctx, test_ctx->ev, -+ test_ctx->ctx, "u1"); -+ fail_unless(test_ctx != NULL, "Cannot create request\n"); -+ tevent_req_set_callback(req, simple_access_check_done, test_ctx); -+ -+ test_loop(test_ctx); -+ test_ctx->done = false; - -- ret = simple_access_check(test_ctx->ctx, "u3", &access_granted); -- fail_unless(ret == EOK, "access_simple_check failed."); -- fail_unless(access_granted == false, "Access granted " -- "while group is not in allow list."); -+ fail_unless(test_ctx->error == EOK, "access_simple_check failed."); -+ fail_unless(test_ctx->access_granted == false, -+ "Access granted while user is in deny list."); -+ -+ req = simple_access_check_send(test_ctx, test_ctx->ev, -+ test_ctx->ctx, "u3"); -+ fail_unless(test_ctx != NULL, "Cannot create request\n"); -+ tevent_req_set_callback(req, simple_access_check_done, test_ctx); -+ -+ test_loop(test_ctx); -+ -+ fail_unless(test_ctx->error == EOK, "access_simple_check failed."); -+ fail_unless(test_ctx->access_granted == false, -+ "Access granted while user is not in allow list."); - } - END_TEST - - START_TEST(test_group_case) - { -- int ret; -- bool access_granted = false; -+ struct tevent_req *req; - -- test_ctx->ctx->allow_groups = discard_const(ulist_1); -+ test_ctx->ctx->allow_groups = discard_const(glist_1_case); - test_ctx->ctx->deny_groups = NULL; - -- ret = simple_access_check(test_ctx->ctx, "U1", &access_granted); -- fail_unless(ret == EOK, "access_simple_check failed."); -- fail_unless(access_granted == false, "Access granted " -- "for group with different case " -- "in case-sensitive domain"); -+ req = simple_access_check_send(test_ctx, test_ctx->ev, -+ test_ctx->ctx, "U1"); -+ fail_unless(test_ctx != NULL, "Cannot create request\n"); -+ tevent_req_set_callback(req, simple_access_check_done, test_ctx); -+ -+ test_loop(test_ctx); -+ test_ctx->done = false; -+ -+ fail_unless(test_ctx->error == EOK, "access_simple_check failed."); -+ fail_unless(test_ctx->access_granted == false, -+ "Access granted for user with different case " -+ "in case-sensitive domain"); - - test_ctx->ctx->domain->case_sensitive = false; - -- ret = simple_access_check(test_ctx->ctx, "U1", &access_granted); -- fail_unless(ret == EOK, "access_simple_check failed."); -- fail_unless(access_granted == true, "Access denied " -- "for group with different case " -- "in case-insensitive domain"); -+ req = simple_access_check_send(test_ctx, test_ctx->ev, -+ test_ctx->ctx, "U1"); -+ fail_unless(test_ctx != NULL, "Cannot create request\n"); -+ tevent_req_set_callback(req, simple_access_check_done, test_ctx); -+ -+ test_loop(test_ctx); -+ test_ctx->done = false; -+ -+ fail_unless(test_ctx->error == EOK, "access_simple_check failed."); -+ fail_unless(test_ctx->access_granted == true, -+ "Access denied for user with different case " -+ "in case-sensitive domain"); - } - END_TEST - -@@ -361,6 +521,7 @@ Suite *access_simple_suite (void) - tcase_add_test(tc_allow_deny, test_deny_empty); - tcase_add_test(tc_allow_deny, test_both_set); - tcase_add_test(tc_allow_deny, test_case); -+ tcase_add_test(tc_allow_deny, test_unknown_user); - suite_add_tcase(s, tc_allow_deny); - - TCase *tc_grp_allow_deny = tcase_create("group allow/deny"); --- -1.8.1.4 - diff --git a/sssd-1.9.4.tar.gz b/sssd-1.9.4.tar.gz deleted file mode 100644 index c3139c3..0000000 --- a/sssd-1.9.4.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:20e39d7c5d89e217b5301f7e75360eb869ac1889701755a598fb3fbed923f4b4 -size 3050325 diff --git a/sssd-1.9.4.tar.gz.asc b/sssd-1.9.4.tar.gz.asc deleted file mode 100644 index a2e92ae..0000000 --- a/sssd-1.9.4.tar.gz.asc +++ /dev/null @@ -1,7 +0,0 @@ ------BEGIN PGP SIGNATURE----- -Version: GnuPG v1.4.13 (GNU/Linux) - -iEYEABECAAYFAlEG6DYACgkQHsardTLnvCXjrgCeMSfawp5NaaIu82GDZOq7EMxL -tqwAmgN3gn9e7y6AzeSBdYCCcPAyLLFo -=hHxo ------END PGP SIGNATURE----- diff --git a/sssd-1.9.5.tar.gz b/sssd-1.9.5.tar.gz new file mode 100644 index 0000000..d7e73fb --- /dev/null +++ b/sssd-1.9.5.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a377c436901e92d689de811d48e37d88764460e889e47bfddd90626f0a8a015c +size 3106988 diff --git a/sssd-1.9.5.tar.gz.asc b/sssd-1.9.5.tar.gz.asc new file mode 100644 index 0000000..e0c1e92 --- /dev/null +++ b/sssd-1.9.5.tar.gz.asc @@ -0,0 +1,7 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.13 (GNU/Linux) + +iEYEABECAAYFAlF2gY4ACgkQHsardTLnvCW6+QCg4VWHi8mlbi6FQufRtUXOTB2j +5OAAniig5/DUZa/mrzUb+8kteg3nanNS +=3VHJ +-----END PGP SIGNATURE----- diff --git a/sssd-sysdb-binary-attrs.diff b/sssd-sysdb-binary-attrs.diff deleted file mode 100644 index 6075737..0000000 --- a/sssd-sysdb-binary-attrs.diff +++ /dev/null @@ -1,102 +0,0 @@ -From 3229c2107e4645240cfc4aa5d262e5330c356a49 Mon Sep 17 00:00:00 2001 -From: Jan Engelhardt -Date: Thu, 21 Feb 2013 13:12:25 +0100 -Subject: [PATCH] sysdb: try dealing with binary-content attributes - -I have here a LDAP user entry which has this attribute - - loginAllowedTimeMap:: - AAAAAAAAAP///38AAP///38AAP///38AAP///38AAP///38AAAAAAAAA - -In the function sysdb_attrs_add_string(), called from -sdap_attrs_add_ldap_attr(), strlen() is called on this blob, which is -the wrong thing to do. The result of strlen is then used to populate -the .v_length member of a struct ldb_val - and this will set it to -zero in this case. (There is also the problem that there may not be -a '\0' at all in the blob.) - -Subsequently, .v_length being 0 makes ldb_modify(), called from -sysdb_set_entry_attr(), return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX. End -result is that users do not get stored in the sysdb, and programs like -`id` or `getent ...` show incomplete information. - -The bug was encountered with sssd-1.8.5. sssd-1.5.11 seemed to behave -fine, but that may not mean that is the absolute lower boundary of -introduction of the problem. ---- - src/db/sysdb.c | 10 ++++++++++ - src/db/sysdb.h | 2 ++ - src/providers/ldap/sdap.c | 7 +++---- - src/providers/ldap/sdap_async.c | 4 ++-- - 4 files changed, 17 insertions(+), 6 deletions(-) - -diff --git a/src/db/sysdb.c b/src/db/sysdb.c -index e7524f4..7c34791 100644 ---- a/src/db/sysdb.c -+++ b/src/db/sysdb.c -@@ -512,6 +512,16 @@ int sysdb_attrs_add_string(struct sysdb_attrs *attrs, - return sysdb_attrs_add_val(attrs, name, &v); - } - -+int sysdb_attrs_add_mem(struct sysdb_attrs *attrs, const char *name, -+ const void *mem, size_t size) -+{ -+ struct ldb_val v; -+ -+ v.data = discard_const(mem); -+ v.length = size; -+ return sysdb_attrs_add_val(attrs, name, &v); -+} -+ - int sysdb_attrs_add_bool(struct sysdb_attrs *attrs, - const char *name, bool value) - { -diff --git a/src/db/sysdb.h b/src/db/sysdb.h -index fff97a8..23cbbb0 100644 ---- a/src/db/sysdb.h -+++ b/src/db/sysdb.h -@@ -250,6 +250,8 @@ int sysdb_attrs_add_val(struct sysdb_attrs *attrs, - const char *name, const struct ldb_val *val); - int sysdb_attrs_add_string(struct sysdb_attrs *attrs, - const char *name, const char *str); -+int sysdb_attrs_add_mem(struct sysdb_attrs *, const char *, -+ const void *, size_t); - int sysdb_attrs_add_bool(struct sysdb_attrs *attrs, - const char *name, bool value); - int sysdb_attrs_add_long(struct sysdb_attrs *attrs, -diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c -index 371121b..988f27d 100644 ---- a/src/providers/ldap/sdap.c -+++ b/src/providers/ldap/sdap.c -@@ -474,10 +474,9 @@ errno_t sdap_parse_deref(TALLOC_CTX *mem_ctx, - for (i=0; dval->vals[i].bv_val; i++) { - DEBUG(9, ("Dereferenced attribute value: %s\n", - dval->vals[i].bv_val)); -- v.data = (uint8_t *) dval->vals[i].bv_val; -- v.length = dval->vals[i].bv_len; -- -- ret = sysdb_attrs_add_val(res[mi]->attrs, name, &v); -+ ret = sysdb_attrs_add_mem(res[mi]->attrs, name, -+ dval->vals[i].bv_val, -+ dval->vals[i].bv_len); - if (ret) goto done; - } - } -diff --git a/src/providers/ldap/sdap_async.c b/src/providers/ldap/sdap_async.c -index 84497b7..b7d9839 100644 ---- a/src/providers/ldap/sdap_async.c -+++ b/src/providers/ldap/sdap_async.c -@@ -2226,8 +2226,8 @@ sdap_attrs_add_ldap_attr(struct sysdb_attrs *ldap_attrs, - DEBUG(SSSDBG_TRACE_INTERNAL, ("Adding %s [%s] to attributes " - "of [%s].\n", desc, el->values[i].data, objname)); - -- ret = sysdb_attrs_add_string(attrs, attr_name, -- (const char *) el->values[i].data); -+ ret = sysdb_attrs_add_mem(attrs, attr_name, el->values[i].data, -+ el->values[i].length); - if (ret) { - return ret; - } --- -1.7.10.4 - diff --git a/sssd.changes b/sssd.changes index bcb412c..2f9e68b 100644 --- a/sssd.changes +++ b/sssd.changes @@ -1,3 +1,27 @@ +------------------------------------------------------------------- +Thu May 2 09:20:49 UTC 2013 - jengelh@inai.de + +- Update to new upstream release 1.9.5 +* Includes a fix for CVE-2013-0287: A simple access provider flaw + prevents intended ACL use when SSSD is configured as an Active + Directory client. +* Fixed spurious password expiration warning that was printed on + login with the Kerberos back end. +* A new option ldap_rfc2307_fallback_to_local_users was added. If + this option is set to true, SSSD is be able to resolve local + group members of LDAP groups. +* Fixed an indexing bug that prevented the contents of autofs maps + from being returned to the automounter deamon in case the map + contained a large number of entries. +* Several fixes for safer handling of Kerberos credential caches + for cases where the ccache is set to be stored in a DIR: type. +- Remove Provide-a-be_get_account_info_send-function.patch, + Add-unit-tests-for-simple-access-test-by-groups.patch, + Do-not-compile-main-in-DP-if-UNIT_TESTING-is-defined.patch, + Resolve-GIDs-in-the-simple-access-provider.patch + (CVE-2013-0287 material is in upstream), + sssd-sysdb-binary-attrs.diff (merged upstream) + ------------------------------------------------------------------- Fri Apr 5 16:35:07 UTC 2013 - jengelh@inai.de diff --git a/sssd.spec b/sssd.spec index 5a76e53..b23a9c9 100644 --- a/sssd.spec +++ b/sssd.spec @@ -17,13 +17,12 @@ Name: sssd -Version: 1.9.4 +Version: 1.9.5 Release: 0 Summary: System Security Services Daemon License: GPL-3.0+ and LGPL-3.0+ Group: System/Daemons Url: https://fedorahosted.org/sssd/ -Requires(postun): pam-config #Git-Clone: git://git.fedorahosted.org/sssd Source: https://fedorahosted.org/released/sssd/sssd-%version.tar.gz @@ -32,13 +31,6 @@ Source3: baselibs.conf Patch1: 0005-implicit-decl.diff Patch2: sssd-ldflags.diff Patch3: sssd-no-ldb-check.diff -Patch4: sssd-sysdb-binary-attrs.diff -# Fixes for CVE-2013-0287 (will be part of 1.9.5) when released -Patch5: Provide-a-be_get_account_info_send-function.patch -Patch6: Add-unit-tests-for-simple-access-test-by-groups.patch -Patch7: Do-not-compile-main-in-DP-if-UNIT_TESTING-is-defined.patch -Patch8: Resolve-GIDs-in-the-simple-access-provider.patch -# End Fixed for CVE-2013-0287 BuildRoot: %{_tmppath}/%{name}-%{version}-build %define servicename sssd @@ -111,6 +103,7 @@ BuildRequires: systemd %if %suse_version >= 1230 BuildRequires: gpg-offline %endif +Requires(postun): pam-config %description Provides a set of daemons to manage access to remote directories and @@ -210,7 +203,7 @@ Security Services Daemon (sssd). %prep %{?gpg_verify: %gpg_verify %{S:2}} %setup -q -%patch -P 1 -P 2 -P 3 -P 4 -P 5 -P 6 -P 7 -P 8 -p1 +%patch -P 1 -P 2 -P 3 -p1 %build %if 0%{?suse_version} < 1210