URL: https://github.com/SSSD/sssd/pull/5608 Author: sumit-bose Title: #5608: nss: fix getsidbyname for IPA user-private-groups Action: opened
PR body: """ Currently the getsidbyname request does not work properly for IPA users due to the way IPA user-private-groups are handled by SSSD. With this patch two different cases, the default automatic user-private-groups where the group is a managed object and manual creation of a user and a groups with UID and GIDs so that the group is a user-private group, are covered. Resolves: https://github.com/SSSD/sssd/issues/5607 :fixes: Fix getsidbyname issues with IPA users with a user-private-group """ To pull the PR as Git branch: git remote add ghsssd https://github.com/SSSD/sssd git fetch ghsssd pull/5608/head:pr5608 git checkout pr5608
From 0adfd7827196eaea44279344eed85289db2ffa31 Mon Sep 17 00:00:00 2001 From: Sumit Bose <sb...@redhat.com> Date: Tue, 27 Apr 2021 10:48:04 +0200 Subject: [PATCH] nss: fix getsidbyname for IPA user-private-groups Currently the getsidbyname request does not work properly for IPA users due to the way IPA user-private-groups are handled by SSSD. With this patch two different cases, the default automatic user-private-groups where the group is a managed object and manual creation of a user and a groups with UID and GIDs so that the group is a user-private group, are covered. Resolves: https://github.com/SSSD/sssd/issues/5607 :fixes: Fix getsidbyname issues with IPA users with a user-private-group --- src/db/sysdb_ops.c | 2 +- .../plugins/cache_req_object_by_name.c | 2 +- src/responder/nss/nss_cmd.c | 5 +- src/responder/nss/nss_protocol_sid.c | 119 ++++++++++++++++-- src/tests/cmocka/test_nss_srv.c | 101 +++++++++++++++ 5 files changed, 218 insertions(+), 11 deletions(-) diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c index 585708abec..a874ae6df6 100644 --- a/src/db/sysdb_ops.c +++ b/src/db/sysdb_ops.c @@ -5259,7 +5259,7 @@ errno_t sysdb_search_object_by_name(TALLOC_CTX *mem_ctx, goto done; } - ret = sysdb_search_object_attr(mem_ctx, domain, filter, attrs, true, res); + ret = sysdb_search_object_attr(mem_ctx, domain, filter, attrs, false, res); done: talloc_free(tmp_ctx); diff --git a/src/responder/common/cache_req/plugins/cache_req_object_by_name.c b/src/responder/common/cache_req/plugins/cache_req_object_by_name.c index 83d00f7750..907f1f3d50 100644 --- a/src/responder/common/cache_req/plugins/cache_req_object_by_name.c +++ b/src/responder/common/cache_req/plugins/cache_req_object_by_name.c @@ -190,7 +190,7 @@ const struct cache_req_plugin cache_req_object_by_name = { .parse_name = true, .ignore_default_domain = false, .bypass_cache = false, - .only_one_result = true, + .only_one_result = false, .search_all_domains = false, .require_enumeration = false, .allow_missing_fqn = false, diff --git a/src/responder/nss/nss_cmd.c b/src/responder/nss/nss_cmd.c index 4698e751c9..a487e1c248 100644 --- a/src/responder/nss/nss_cmd.c +++ b/src/responder/nss/nss_cmd.c @@ -1121,7 +1121,10 @@ static errno_t nss_cmd_endservent(struct cli_ctx *cli_ctx) static errno_t nss_cmd_getsidbyname(struct cli_ctx *cli_ctx) { - const char *attrs[] = { SYSDB_SID_STR, NULL }; + /* The attributes besides SYSDB_SID_STR are needed to handle some corner + * cases with respect to user-private-groups */ + const char *attrs[] = { SYSDB_SID_STR, SYSDB_UIDNUM, SYSDB_GIDNUM, + SYSDB_OBJECTCATEGORY, NULL }; return nss_getby_name(cli_ctx, false, CACHE_REQ_OBJECT_BY_NAME, attrs, SSS_MC_NONE, nss_protocol_fill_sid); diff --git a/src/responder/nss/nss_protocol_sid.c b/src/responder/nss/nss_protocol_sid.c index 96cb8617bc..0fd8d48dad 100644 --- a/src/responder/nss/nss_protocol_sid.c +++ b/src/responder/nss/nss_protocol_sid.c @@ -87,13 +87,115 @@ nss_get_id_type(struct nss_cmd_ctx *cmd_ctx, return EOK; } +static errno_t +nss_get_sid_id_type(struct nss_cmd_ctx *cmd_ctx, + struct cache_req_result *result, + const char **_sid, + enum sss_id_type *_type) +{ + errno_t ret; + size_t c; + const char *tmp; + const char *user_sid = NULL; + const char *group_sid = NULL; + uint64_t user_uid = 0; + uint64_t user_gid = 0; + uint64_t group_gid = 0; + enum sss_id_type ltype; + + if (result->count == 1) { + *_sid = ldb_msg_find_attr_as_string(result->msgs[0], + SYSDB_SID_STR, NULL); + if (*_sid == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Missing SID.\n"); + return EINVAL; + } + return nss_get_id_type(cmd_ctx, result, _type); + } + + for (c = 0; c < result->count; c++) { + ret = find_sss_id_type(result->msgs[c], + false /* we are only interested in the type + * of the object, so mpg setting can + * be ignored */, + <ype); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Unable to find ID type, ignored [%d][%s].\n", + ret, sss_strerror(ret)); + continue; + } + + if (ltype == SSS_ID_TYPE_GID) { + tmp = ldb_msg_find_attr_as_string(result->msgs[c], + SYSDB_SID_STR, NULL); + if (tmp == NULL) { + continue; + } + if (tmp != NULL && group_sid != NULL) { + DEBUG(SSSDBG_OP_FAILURE, + "Search for SID found multiple users with a SID, " + "request failed.\n"); + return EINVAL; + } + group_sid = tmp; + group_gid = ldb_msg_find_attr_as_uint64(result->msgs[c], + SYSDB_GIDNUM, 0); + } else { + tmp = ldb_msg_find_attr_as_string(result->msgs[c], + SYSDB_SID_STR, NULL); + if (tmp == NULL) { + continue; + } + if (tmp != NULL && user_sid != NULL) { + DEBUG(SSSDBG_OP_FAILURE, + "Search for SID found multiple users with a SID, " + "request failed.\n"); + return EINVAL; + } + user_sid = tmp; + user_uid = ldb_msg_find_attr_as_uint64(result->msgs[c], + SYSDB_UIDNUM, 0); + user_gid = ldb_msg_find_attr_as_uint64(result->msgs[c], + SYSDB_GIDNUM, 0); + } + } + + if (user_sid == NULL && group_sid == NULL) { + /* No SID in the results */ + return ENOENT; + } else if (user_sid != NULL && group_sid == NULL) { + /* There is only one user with a SID in the results */ + *_sid = user_sid; + *_type = SSS_ID_TYPE_UID; + } else if (user_sid == NULL && group_sid != NULL) { + /* There is only one group with a SID in the results */ + *_sid = group_sid; + *_type = SSS_ID_TYPE_GID; + } else if (user_sid != NULL && group_sid != NULL && user_uid != 0 + && user_uid == user_gid && user_gid == group_gid) { + /* Manually created user-private-group */ + *_sid = user_sid; + *_type = SSS_ID_TYPE_UID; + } else { + DEBUG(SSSDBG_OP_FAILURE, + "Found user with SID [%s] and group with SID [%s] during a " + "single request, cannot handle this case.\n", + user_sid, group_sid); + /* Unrelated user and group both with SIDs are returned, we cannot + * handle this case. */ + return EINVAL; + } + + return EOK; +} + errno_t nss_protocol_fill_sid(struct nss_ctx *nss_ctx, struct nss_cmd_ctx *cmd_ctx, struct sss_packet *packet, struct cache_req_result *result) { - struct ldb_message *msg = result->msgs[0]; struct sized_string sz_sid; enum sss_id_type id_type; const char *sid; @@ -102,17 +204,11 @@ nss_protocol_fill_sid(struct nss_ctx *nss_ctx, uint8_t *body; errno_t ret; - ret = nss_get_id_type(cmd_ctx, result, &id_type); + ret = nss_get_sid_id_type(cmd_ctx, result, &sid, &id_type); if (ret != EOK) { return ret; } - sid = ldb_msg_find_attr_as_string(msg, SYSDB_SID_STR, NULL); - if (sid == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "Missing SID.\n"); - return EINVAL; - } - to_sized_string(&sz_sid, sid); ret = sss_packet_grow(packet, sz_sid.len + 3 * sizeof(uint32_t)); @@ -242,6 +338,13 @@ nss_protocol_fill_orig(struct nss_ctx *nss_ctx, SYSDB_ORIG_MEMBEROF, NULL }; + if (result->count != 1) { + DEBUG(SSSDBG_OP_FAILURE, + "Unexpected number of results [%u], expected [1].\n", + result->count); + return EINVAL; + } + tmp_ctx = talloc_new(NULL); if (tmp_ctx == NULL) { return ENOMEM; diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c index 2b6b8ca280..5f5a383a58 100644 --- a/src/tests/cmocka/test_nss_srv.c +++ b/src/tests/cmocka/test_nss_srv.c @@ -4109,6 +4109,21 @@ struct passwd sid_user = { .pw_passwd = discard_const("*"), }; +struct passwd sid_user_upg = { + .pw_name = discard_const("testusersidupg"), + .pw_uid = 5678, + .pw_gid = 5678, + .pw_dir = discard_const("/home/testusersidupg"), + .pw_gecos = discard_const("test user upg"), + .pw_shell = discard_const("/bin/sh"), + .pw_passwd = discard_const("*"), +}; + +struct group sid_user_group = { + .gr_name = discard_const("testusersidupg"), + .gr_gid = 5678, +}; + static int test_nss_getsidbyname_check(uint32_t status, uint8_t *body, size_t blen) @@ -4168,6 +4183,88 @@ void test_nss_getsidbyname(void **state) assert_int_equal(ret, EOK); } +void test_nss_getsidbyname_ipa_upg(void **state) +{ + errno_t ret; + struct sysdb_attrs *attrs; + const char *testuser_sid = "S-1-2-3-4"; + + attrs = sysdb_new_attrs(nss_test_ctx); + assert_non_null(attrs); + + ret = sysdb_attrs_add_string(attrs, SYSDB_SID_STR, testuser_sid); + assert_int_equal(ret, EOK); + + ret = store_user(nss_test_ctx, nss_test_ctx->tctx->dom, + &sid_user_upg, attrs, 0); + assert_int_equal(ret, EOK); + + ret = store_group(nss_test_ctx, nss_test_ctx->tctx->dom, + &sid_user_group, NULL, 0); + assert_int_equal(ret, EOK); + + mock_input_user_or_group("testusersid"); + will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETSIDBYNAME); + will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); + + will_return(test_nss_getsidbyname_check, testuser_sid); + + /* Query for that user, call a callback when command finishes */ + set_cmd_cb(test_nss_getsidbyname_check); + ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETSIDBYNAME, + nss_test_ctx->nss_cmds); + assert_int_equal(ret, EOK); + + /* Wait until the test finishes with EOK */ + ret = test_ev_loop(nss_test_ctx->tctx); + assert_int_equal(ret, EOK); +} + +void test_nss_getsidbyname_ipa_upg_manual(void **state) +{ + errno_t ret; + struct sysdb_attrs *attrs; + const char *testuser_sid = "S-1-2-3-4"; + const char *testgroup_sid = "S-1-2-3-5"; + + attrs = sysdb_new_attrs(nss_test_ctx); + assert_non_null(attrs); + + ret = sysdb_attrs_add_string(attrs, SYSDB_SID_STR, testuser_sid); + assert_int_equal(ret, EOK); + + ret = store_user(nss_test_ctx, nss_test_ctx->tctx->dom, + &sid_user_upg, attrs, 0); + assert_int_equal(ret, EOK); + + talloc_free(attrs); + attrs = sysdb_new_attrs(nss_test_ctx); + assert_non_null(attrs); + + ret = sysdb_attrs_add_string(attrs, SYSDB_SID_STR, testgroup_sid); + assert_int_equal(ret, EOK); + + ret = store_group(nss_test_ctx, nss_test_ctx->tctx->dom, + &sid_user_group, attrs, 0); + assert_int_equal(ret, EOK); + + mock_input_user_or_group("testusersid"); + will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETSIDBYNAME); + will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); + + will_return(test_nss_getsidbyname_check, testuser_sid); + + /* Query for that user, call a callback when command finishes */ + set_cmd_cb(test_nss_getsidbyname_check); + ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETSIDBYNAME, + nss_test_ctx->nss_cmds); + assert_int_equal(ret, EOK); + + /* Wait until the test finishes with EOK */ + ret = test_ev_loop(nss_test_ctx->tctx); + assert_int_equal(ret, EOK); +} + void test_nss_getsidbyid(void **state) { errno_t ret; @@ -5667,6 +5764,8 @@ int main(int argc, const char *argv[]) nss_subdom_test_teardown), cmocka_unit_test_setup_teardown(test_nss_getsidbyname, nss_test_setup, nss_test_teardown), + cmocka_unit_test_setup_teardown(test_nss_getsidbyname_ipa_upg, + nss_test_setup, nss_test_teardown), cmocka_unit_test_setup_teardown(test_nss_getsidbyid, nss_test_setup, nss_test_teardown), cmocka_unit_test_setup_teardown(test_nss_getsidbyuid, @@ -5685,6 +5784,8 @@ int main(int argc, const char *argv[]) nss_test_setup, nss_test_teardown), cmocka_unit_test_setup_teardown(test_nss_getsidbyname_neg, nss_test_setup, nss_test_teardown), + cmocka_unit_test_setup_teardown(test_nss_getsidbyname_ipa_upg_manual, + nss_test_setup, nss_test_teardown), cmocka_unit_test_setup_teardown(test_nss_getpwnam_ex, nss_test_setup, nss_test_teardown), cmocka_unit_test_setup_teardown(test_nss_getpwuid_ex,
_______________________________________________ sssd-devel mailing list -- sssd-devel@lists.fedorahosted.org To unsubscribe send an email to sssd-devel-le...@lists.fedorahosted.org Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedorahosted.org/archives/list/sssd-devel@lists.fedorahosted.org Do not reply to spam on the list, report it: https://pagure.io/fedora-infrastructure