From 9f89df166194aa1df66b32c40b748dd277d1640f Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Dec 06 2016 15:40:36 +0000 Subject: import sssd-1.14.0-43.el7_3.4 --- diff --git a/SOURCES/0144-sysdb-add-parent_dom-to-sysdb_get_direct_parents.patch b/SOURCES/0144-sysdb-add-parent_dom-to-sysdb_get_direct_parents.patch new file mode 100644 index 0000000..7cf09f2 --- /dev/null +++ b/SOURCES/0144-sysdb-add-parent_dom-to-sysdb_get_direct_parents.patch @@ -0,0 +1,124 @@ +From b368dca11e715400da64348a17049abf5b072f57 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Tue, 18 Oct 2016 14:59:19 +0200 +Subject: [PATCH 144/151] sysdb: add parent_dom to sysdb_get_direct_parents() + +Currently sysdb_get_direct_parents() only return direct parents from the +same domain as the child object. In setups with sub-domains this might +not be sufficient. A new option parent_dom is added which allows to +specify a domain the direct parents should be lookup up in. If it is +NULL the whole cache is searched. + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 3dd4c3eca80e9223a65f3318821bd0fb5b45aedd) +--- + src/db/sysdb.h | 21 +++++++++++++++++++++ + src/db/sysdb_search.c | 7 ++++++- + src/providers/ldap/sdap_async_initgroups.c | 11 +++++++---- + 3 files changed, 34 insertions(+), 5 deletions(-) + +diff --git a/src/db/sysdb.h b/src/db/sysdb.h +index 8713efa6e8fcc6fb620340fe152989a5dae58434..4164657c2b329a240d46fe3ecdfb4b2eefffc5b3 100644 +--- a/src/db/sysdb.h ++++ b/src/db/sysdb.h +@@ -1135,8 +1135,29 @@ errno_t sysdb_remove_attrs(struct sss_domain_info *domain, + enum sysdb_member_type type, + char **remove_attrs); + ++/** ++ * @brief Return direct parents of an object in the cache ++ * ++ * @param[in] mem_ctx Memory context the result should be allocated ++ * on ++ * @param[in] dom domain the object is in ++ * @param[in] parent_dom domain which should be searched for direct ++ * parents if NULL all domains in the given cache ++ * are searched ++ * @param[in] mtype Type of the object, SYSDB_MEMBER_USER or ++ * SYSDB_MEMBER_GROUP ++ * @param[in] name Name of the object ++ * @param[out] _direct_parents List of names of the direct parent groups ++ * ++ * ++ * @return ++ * - EOK: success ++ * - EINVAL: wrong mtype ++ * - ENOMEM: Memory allocation failed ++ */ + errno_t sysdb_get_direct_parents(TALLOC_CTX *mem_ctx, + struct sss_domain_info *dom, ++ struct sss_domain_info *parent_dom, + enum sysdb_member_type mtype, + const char *name, + char ***_direct_parents); +diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c +index cfee5784dbadd692f30d0758e7e5c3c9fb2814cb..4d63c3838a49392bbf2a57aeb6f7740f4d4fbdcd 100644 +--- a/src/db/sysdb_search.c ++++ b/src/db/sysdb_search.c +@@ -1981,6 +1981,7 @@ done: + + errno_t sysdb_get_direct_parents(TALLOC_CTX *mem_ctx, + struct sss_domain_info *dom, ++ struct sss_domain_info *parent_dom, + enum sysdb_member_type mtype, + const char *name, + char ***_direct_parents) +@@ -2029,7 +2030,11 @@ errno_t sysdb_get_direct_parents(TALLOC_CTX *mem_ctx, + goto done; + } + +- basedn = sysdb_group_base_dn(tmp_ctx, dom); ++ if (parent_dom == NULL) { ++ basedn = sysdb_base_dn(dom->sysdb, tmp_ctx); ++ } else { ++ basedn = sysdb_group_base_dn(tmp_ctx, parent_dom); ++ } + if (!basedn) { + ret = ENOMEM; + goto done; +diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c +index f9593f0dfaa2dc6e33fd6c9d1f0c9b78cad3a1d9..77324d0ee9eb2ad2fc35c2098d6c9c23a62747c9 100644 +--- a/src/providers/ldap/sdap_async_initgroups.c ++++ b/src/providers/ldap/sdap_async_initgroups.c +@@ -1301,7 +1301,8 @@ sdap_initgr_store_user_memberships(struct sdap_initgr_nested_state *state) + } + } + +- ret = sysdb_get_direct_parents(tmp_ctx, state->dom, SYSDB_MEMBER_USER, ++ ret = sysdb_get_direct_parents(tmp_ctx, state->dom, state->dom, ++ SYSDB_MEMBER_USER, + state->username, &sysdb_parent_name_list); + if (ret) { + DEBUG(SSSDBG_CRIT_FAILURE, +@@ -1388,7 +1389,7 @@ sdap_initgr_nested_get_membership_diff(TALLOC_CTX *mem_ctx, + goto done; + } + +- ret = sysdb_get_direct_parents(tmp_ctx, dom, SYSDB_MEMBER_GROUP, ++ ret = sysdb_get_direct_parents(tmp_ctx, dom, dom, SYSDB_MEMBER_GROUP, + group_name, &sysdb_parents_names_list); + if (ret) { + DEBUG(SSSDBG_CRIT_FAILURE, +@@ -2070,7 +2071,8 @@ rfc2307bis_group_memberships_build(hash_entry_t *item, void *user_data) + goto done; + } + +- ret = sysdb_get_direct_parents(tmp_ctx, mstate->dom, SYSDB_MEMBER_GROUP, ++ ret = sysdb_get_direct_parents(tmp_ctx, mstate->dom, mstate->dom, ++ SYSDB_MEMBER_GROUP, + group_name, &sysdb_parents_names_list); + if (ret) { + DEBUG(SSSDBG_CRIT_FAILURE, +@@ -2130,7 +2132,8 @@ errno_t save_rfc2307bis_user_memberships( + } + in_transaction = true; + +- ret = sysdb_get_direct_parents(tmp_ctx, state->dom, SYSDB_MEMBER_USER, ++ ret = sysdb_get_direct_parents(tmp_ctx, state->dom, state->dom, ++ SYSDB_MEMBER_USER, + state->name, &sysdb_parent_name_list); + if (ret) { + DEBUG(SSSDBG_CRIT_FAILURE, +-- +2.7.4 + diff --git a/SOURCES/0145-sdap-make-some-nested-group-related-calls-public.patch b/SOURCES/0145-sdap-make-some-nested-group-related-calls-public.patch new file mode 100644 index 0000000..abba383 --- /dev/null +++ b/SOURCES/0145-sdap-make-some-nested-group-related-calls-public.patch @@ -0,0 +1,80 @@ +From f0e6ed1942f1a4263a88a0c02d866d616448668f Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Tue, 18 Oct 2016 18:16:30 +0200 +Subject: [PATCH 145/151] sdap: make some nested group related calls public + +sdap_nested_groups_store() and rfc2307bis_nested_groups_send/recv() will +be reused for domain local group lookups. + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 49d3f0a487d55571b2bdc9d3f8280b304b964b9d) +--- + src/providers/ldap/sdap_async_initgroups.c | 12 ++---------- + src/providers/ldap/sdap_async_private.h | 16 ++++++++++++++++ + 2 files changed, 18 insertions(+), 10 deletions(-) + +diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c +index 77324d0ee9eb2ad2fc35c2098d6c9c23a62747c9..f1ba65a98b07a593b0e3a722d0b2c56c8e4b821e 100644 +--- a/src/providers/ldap/sdap_async_initgroups.c ++++ b/src/providers/ldap/sdap_async_initgroups.c +@@ -622,7 +622,7 @@ static int sdap_initgr_rfc2307_recv(struct tevent_req *req) + } + + /* ==Common code for pure RFC2307bis and IPA/AD========================= */ +-static errno_t ++errno_t + sdap_nested_groups_store(struct sysdb_ctx *sysdb, + struct sss_domain_info *domain, + struct sdap_options *opts, +@@ -1558,14 +1558,6 @@ static void sdap_initgr_rfc2307bis_process(struct tevent_req *subreq); + static void sdap_initgr_rfc2307bis_done(struct tevent_req *subreq); + errno_t save_rfc2307bis_user_memberships( + struct sdap_initgr_rfc2307bis_state *state); +-struct tevent_req *rfc2307bis_nested_groups_send( +- TALLOC_CTX *mem_ctx, struct tevent_context *ev, +- struct sdap_options *opts, struct sysdb_ctx *sysdb, +- struct sss_domain_info *dom, struct sdap_handle *sh, +- struct sdap_search_base **search_bases, +- struct sysdb_attrs **groups, size_t num_groups, +- hash_table_t *group_hash, size_t nesting); +-static errno_t rfc2307bis_nested_groups_recv(struct tevent_req *req); + + static struct tevent_req *sdap_initgr_rfc2307bis_send( + TALLOC_CTX *memctx, +@@ -2616,7 +2608,7 @@ static void rfc2307bis_nested_groups_process(struct tevent_req *subreq) + tevent_req_set_callback(subreq, rfc2307bis_nested_groups_done, req); + } + +-static errno_t rfc2307bis_nested_groups_recv(struct tevent_req *req) ++errno_t rfc2307bis_nested_groups_recv(struct tevent_req *req) + { + TEVENT_REQ_RETURN_ON_ERROR(req); + return EOK; +diff --git a/src/providers/ldap/sdap_async_private.h b/src/providers/ldap/sdap_async_private.h +index f09ddb71f48080251e61b8a850ccb8c9b5058331..4af4f7144d8855e4ed705f6a64e0a7818bc0b9a9 100644 +--- a/src/providers/ldap/sdap_async_private.h ++++ b/src/providers/ldap/sdap_async_private.h +@@ -157,4 +157,20 @@ errno_t sdap_check_ad_group_type(struct sss_domain_info *dom, + struct sysdb_attrs *group_attrs, + const char *group_name, + bool *_need_filter); ++ ++struct tevent_req *rfc2307bis_nested_groups_send( ++ TALLOC_CTX *mem_ctx, struct tevent_context *ev, ++ struct sdap_options *opts, struct sysdb_ctx *sysdb, ++ struct sss_domain_info *dom, struct sdap_handle *sh, ++ struct sdap_search_base **search_bases, ++ struct sysdb_attrs **groups, size_t num_groups, ++ hash_table_t *group_hash, size_t nesting); ++errno_t rfc2307bis_nested_groups_recv(struct tevent_req *req); ++ ++errno_t sdap_nested_groups_store(struct sysdb_ctx *sysdb, ++ struct sss_domain_info *domain, ++ struct sdap_options *opts, ++ struct sysdb_attrs **groups, ++ unsigned long count); ++ + #endif /* _SDAP_ASYNC_PRIVATE_H_ */ +-- +2.7.4 + diff --git a/SOURCES/0146-LDAP-AD-resolve-domain-local-groups-for-remote-users.patch b/SOURCES/0146-LDAP-AD-resolve-domain-local-groups-for-remote-users.patch new file mode 100644 index 0000000..3e2d38d --- /dev/null +++ b/SOURCES/0146-LDAP-AD-resolve-domain-local-groups-for-remote-users.patch @@ -0,0 +1,683 @@ +From 2341059ba000d4fa87691f84bf3c39822b38aecb Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Tue, 18 Oct 2016 18:18:44 +0200 +Subject: [PATCH 146/151] LDAP/AD: resolve domain local groups for remote users + +If a user from a trusted domain in the same forest is a direct or +indirect member of domain local groups from the local domain those +memberships must be resolved as well. Since those domain local groups +are not valid in the trusted domain a DC from the trusted domain which +is used to lookup the user data is not aware of them. As a consequence +those memberships must be resolved against a local DC in a second step. + +Resolves https://fedorahosted.org/sssd/ticket/3206 + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 25699846bd1c9f8bb513b6271eb4366ab682fbd2) +--- + src/db/sysdb.h | 2 + + src/providers/ldap/sdap_async_initgroups.c | 158 +++++++++- + src/providers/ldap/sdap_async_initgroups_ad.c | 407 ++++++++++++++++++++++++++ + src/providers/ldap/sdap_async_private.h | 10 + + 4 files changed, 570 insertions(+), 7 deletions(-) + +diff --git a/src/db/sysdb.h b/src/db/sysdb.h +index 4164657c2b329a240d46fe3ecdfb4b2eefffc5b3..a0279fb249e1258c9cb73a4fcab55e4b242c61f3 100644 +--- a/src/db/sysdb.h ++++ b/src/db/sysdb.h +@@ -224,6 +224,8 @@ + SYSDB_OVERRIDE_DN, \ + SYSDB_OVERRIDE_OBJECT_DN, \ + SYSDB_DEFAULT_OVERRIDE_NAME, \ ++ SYSDB_UUID, \ ++ SYSDB_ORIG_DN, \ + NULL} + + #define SYSDB_GRSRC_ATTRS {SYSDB_NAME, SYSDB_GIDNUM, \ +diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c +index f1ba65a98b07a593b0e3a722d0b2c56c8e4b821e..8eaba261c49082d086df9f19464ac0f40fae71fb 100644 +--- a/src/providers/ldap/sdap_async_initgroups.c ++++ b/src/providers/ldap/sdap_async_initgroups.c +@@ -2317,6 +2317,7 @@ static errno_t rfc2307bis_nested_groups_step(struct tevent_req *req) + struct sdap_rfc2307bis_nested_ctx *state = + tevent_req_data(req, struct sdap_rfc2307bis_nested_ctx); + char *oc_list; ++ const char *class; + + tmp_ctx = talloc_new(state); + if (!tmp_ctx) { +@@ -2324,9 +2325,21 @@ static errno_t rfc2307bis_nested_groups_step(struct tevent_req *req) + goto done; + } + +- ret = sdap_get_group_primary_name(state, state->opts, +- state->groups[state->group_iter], +- state->dom, &state->primary_name); ++ ret = sysdb_attrs_get_string(state->groups[state->group_iter], ++ SYSDB_OBJECTCLASS, &class); ++ if (ret == EOK) { ++ /* If there is a objectClass attribute the object is coming from the ++ * cache and the name attribute of the object already has the primary ++ * name. ++ * If the objectClass attribute is missing the object is coming from ++ * LDAP and we have to find the primary name first. */ ++ ret = sysdb_attrs_get_string(state->groups[state->group_iter], ++ SYSDB_NAME, &state->primary_name); ++ } else { ++ ret = sdap_get_group_primary_name(state, state->opts, ++ state->groups[state->group_iter], ++ state->dom, &state->primary_name); ++ } + if (ret != EOK) { + goto done; + } +@@ -3069,6 +3082,103 @@ fail: + tevent_req_error(req, ret); + } + ++static void sdap_ad_check_domain_local_groups_done(struct tevent_req *subreq); ++ ++errno_t sdap_ad_check_domain_local_groups(struct tevent_req *req) ++{ ++ struct sdap_get_initgr_state *state = tevent_req_data(req, ++ struct sdap_get_initgr_state); ++ int ret; ++ struct sdap_domain *local_sdom; ++ const char *orig_name; ++ const char *sysdb_name; ++ struct ldb_result *res; ++ struct tevent_req *subreq; ++ struct sysdb_attrs **groups; ++ ++ /* We only need to check for domain local groups in the AD case and if the ++ * user is not from our domain, i.e. if the user comes from a sub-domain. ++ */ ++ if (state->opts->schema_type != SDAP_SCHEMA_AD ++ || !IS_SUBDOMAIN(state->dom) ++ || !dp_target_enabled(state->id_ctx->be->provider, "ad", DPT_ID)) { ++ return EOK; ++ } ++ ++ local_sdom = sdap_domain_get(state->id_ctx->opts, state->dom->parent); ++ if (local_sdom == NULL || local_sdom->pvt == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "No ID ctx available for [%s].\n", ++ state->dom->parent->name); ++ return EINVAL; ++ } ++ ++ ret = sysdb_attrs_get_string(state->orig_user, SYSDB_NAME, &orig_name); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Missing name in user object.\n"); ++ return ret; ++ } ++ ++ sysdb_name = sss_create_internal_fqname(state, orig_name, state->dom->name); ++ if (sysdb_name == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "sss_create_internal_fqname failed.\n"); ++ return ENOMEM; ++ } ++ ++ ret = sysdb_initgroups(state, state->dom, sysdb_name, &res); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_initgroups failed for user [%s].\n", ++ sysdb_name); ++ return ret; ++ } ++ ++ if (res->count == 0) { ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "sysdb_initgroups returned no results for user [%s].\n", ++ sysdb_name); ++ return EINVAL; ++ } ++ ++ /* The user object, the first entry in the res->msgs, is included as well ++ * to cover the case where the remote user is directly added to ++ * a domain local group. */ ++ ret = sysdb_msg2attrs(state, res->count, res->msgs, &groups); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, "sysdb_msg2attrs failed.\n"); ++ return ret; ++ } ++ ++ subreq = sdap_ad_get_domain_local_groups_send(state, state->ev, local_sdom, ++ state->opts, state->sysdb, state->dom->parent, ++ groups, res->count); ++ if (subreq == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "sdap_ad_get_domain_local_groups_send failed.\n"); ++ return ENOMEM; ++ } ++ ++ tevent_req_set_callback(subreq, sdap_ad_check_domain_local_groups_done, ++ req); ++ ++ return EAGAIN; ++} ++ ++static void sdap_ad_check_domain_local_groups_done(struct tevent_req *subreq) ++{ ++ struct tevent_req *req = tevent_req_callback_data(subreq, ++ struct tevent_req); ++ int ret; ++ ++ ret = sdap_ad_get_domain_local_groups_recv(subreq); ++ talloc_zfree(subreq); ++ if (ret != EOK) { ++ tevent_req_error(req, ret); ++ return; ++ } ++ ++ tevent_req_done(req); ++ ++ return; ++} ++ + static void sdap_get_initgr_pgid(struct tevent_req *req); + static void sdap_get_initgr_done(struct tevent_req *subreq) + { +@@ -3201,8 +3311,6 @@ static void sdap_get_initgr_done(struct tevent_req *subreq) + if (ret == EOK) { + DEBUG(SSSDBG_TRACE_FUNC, + "Primary group already cached, nothing to do.\n"); +- ret = EOK; +- goto done; + } else { + gid = talloc_asprintf(state, "%lu", (unsigned long)primary_gid); + if (gid == NULL) { +@@ -3219,10 +3327,28 @@ static void sdap_get_initgr_done(struct tevent_req *subreq) + goto done; + } + tevent_req_set_callback(subreq, sdap_get_initgr_pgid, req); ++ ++ talloc_free(tmp_ctx); ++ return; + } + +- talloc_free(tmp_ctx); +- return; ++ ret = sdap_ad_check_domain_local_groups(req); ++ if (ret == EAGAIN) { ++ DEBUG(SSSDBG_TRACE_ALL, ++ "Checking for domain local group memberships.\n"); ++ talloc_free(tmp_ctx); ++ return; ++ } else if (ret == EOK) { ++ DEBUG(SSSDBG_TRACE_ALL, ++ "No need to check for domain local group memberships.\n"); ++ } else { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "sdap_ad_check_domain_local_groups failed, " ++ "meberships to domain local groups might be missing.\n"); ++ /* do not let the request fail completely because we already have at ++ * least "some" groups */ ++ ret = EOK; ++ } + + done: + talloc_free(tmp_ctx); +@@ -3247,7 +3373,25 @@ static void sdap_get_initgr_pgid(struct tevent_req *subreq) + return; + } + ++ ret = sdap_ad_check_domain_local_groups(req); ++ if (ret == EAGAIN) { ++ DEBUG(SSSDBG_TRACE_ALL, ++ "Checking for domain local group memberships.\n"); ++ return; ++ } else if (ret == EOK) { ++ DEBUG(SSSDBG_TRACE_ALL, ++ "No need to check for domain local group memberships.\n"); ++ } else { ++ DEBUG(SSSDBG_OP_FAILURE, "sdap_ad_check_domain_local_groups failed.\n"); ++ DEBUG(SSSDBG_OP_FAILURE, ++ "sdap_ad_check_domain_local_groups failed, " ++ "meberships to domain local groups might be missing.\n"); ++ /* do not let the request fail completely because we already have at ++ * least "some" groups */ ++ } ++ + tevent_req_done(req); ++ return; + } + + int sdap_get_initgr_recv(struct tevent_req *req) +diff --git a/src/providers/ldap/sdap_async_initgroups_ad.c b/src/providers/ldap/sdap_async_initgroups_ad.c +index ad54c1fb837eb4b8e123a1c230feb697eb37bb41..1fee4ab43a6c13803a088ffa4695dde7f39b3d2b 100644 +--- a/src/providers/ldap/sdap_async_initgroups_ad.c ++++ b/src/providers/ldap/sdap_async_initgroups_ad.c +@@ -1412,6 +1412,413 @@ static errno_t sdap_ad_tokengroups_initgr_posix_recv(struct tevent_req *req) + return EOK; + } + ++struct sdap_ad_get_domain_local_groups_state { ++ struct tevent_context *ev; ++ struct sdap_id_conn_ctx *conn; ++ struct sdap_options *opts; ++ struct sdap_id_op *op; ++ struct sysdb_ctx *sysdb; ++ struct sss_domain_info *dom; ++ int dp_error; ++ ++ struct sdap_search_base **search_bases; ++ struct sysdb_attrs **groups; ++ size_t num_groups; ++ hash_table_t *group_hash; ++}; ++ ++static void ++sdap_ad_get_domain_local_groups_connect_done(struct tevent_req *subreq); ++static void sdap_ad_get_domain_local_groups_done(struct tevent_req *subreq); ++ ++struct tevent_req * ++sdap_ad_get_domain_local_groups_send(TALLOC_CTX *mem_ctx, ++ struct tevent_context *ev, ++ struct sdap_domain *local_sdom, ++ struct sdap_options *opts, ++ struct sysdb_ctx *sysdb, ++ struct sss_domain_info *dom, ++ struct sysdb_attrs **groups, ++ size_t num_groups) ++{ ++ struct sdap_ad_get_domain_local_groups_state *state; ++ struct tevent_req *req; ++ struct tevent_req *subreq; ++ struct ad_id_ctx *ad_id_ctx; ++ errno_t ret; ++ ++ req = tevent_req_create(mem_ctx, &state, ++ struct sdap_ad_get_domain_local_groups_state); ++ if (req == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); ++ return NULL; ++ } ++ ++ state->ev = ev; ++ ad_id_ctx = talloc_get_type(local_sdom->pvt, struct ad_id_ctx); ++ state->conn = ad_id_ctx->ldap_ctx; ++ state->opts = opts; ++ state->sysdb = sysdb; ++ state->dom = dom; ++ state->search_bases = state->conn->id_ctx->opts->sdom->group_search_bases; ++ state->groups = groups; ++ state->num_groups = num_groups; ++ ++ ret = sss_hash_create(state, 32, &state->group_hash); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, "sss_hash_create failed.\n"); ++ goto fail; ++ } ++ ++ state->op = sdap_id_op_create(state, state->conn->conn_cache); ++ if (state->op == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create failed\n"); ++ ret = ENOMEM; ++ goto fail; ++ } ++ ++ subreq = sdap_id_op_connect_send(state->op, state, &ret); ++ if (subreq == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_connect_send failed.\n"); ++ goto fail; ++ } ++ ++ tevent_req_set_callback(subreq, ++ sdap_ad_get_domain_local_groups_connect_done, req); ++ ++ return req; ++ ++fail: ++ tevent_req_error(req, ret); ++ tevent_req_post(req, ev); ++ return req; ++} ++ ++static void ++sdap_ad_get_domain_local_groups_connect_done(struct tevent_req *subreq) ++{ ++ ++ struct tevent_req *req = tevent_req_callback_data(subreq, ++ struct tevent_req); ++ struct sdap_ad_get_domain_local_groups_state *state = tevent_req_data(req, ++ struct sdap_ad_get_domain_local_groups_state); ++ int dp_error = DP_ERR_FATAL; ++ int ret; ++ ++ ret = sdap_id_op_connect_recv(subreq, &dp_error); ++ talloc_zfree(subreq); ++ ++ if (ret != EOK) { ++ state->dp_error = dp_error; ++ tevent_req_error(req, ret); ++ return; ++ } ++ subreq = rfc2307bis_nested_groups_send(state, state->ev, state->opts, ++ state->sysdb, state->dom, ++ sdap_id_op_handle(state->op), ++ state->search_bases, ++ state->groups, state->num_groups, ++ state->group_hash, 0); ++ if (subreq == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "rfc2307bis_nested_groups_send failed.\n"); ++ state->dp_error = DP_ERR_FATAL; ++ tevent_req_error(req, ENOMEM); ++ return; ++ } ++ ++ tevent_req_set_callback(subreq, ++ sdap_ad_get_domain_local_groups_done, req); ++ ++ return; ++} ++ ++struct sdap_nested_group { ++ struct sysdb_attrs *group; ++ struct sysdb_attrs **ldap_parents; ++ size_t parents_count; ++}; ++ ++static errno_t ++sdap_ad_get_domain_local_groups_parse_parents(TALLOC_CTX *mem_ctx, ++ struct sdap_nested_group *gr, ++ struct sss_domain_info *dom, ++ struct sysdb_ctx *sysdb, ++ struct sdap_options *opts, ++ const char **_sysdb_name, ++ enum sysdb_member_type *_type, ++ char ***_add_list, ++ char ***_del_list) ++{ ++ int ret; ++ size_t c; ++ char **groupnamelist = NULL; ++ struct sysdb_attrs *groups[1]; ++ enum sysdb_member_type type; ++ const char *sysdb_name; ++ const char *group_name; ++ const char *class; ++ struct sss_domain_info *obj_dom; ++ char *local_groups_base_dn; ++ char **cached_local_parents = NULL; ++ char **add_list = NULL; ++ char **del_list = NULL; ++ TALLOC_CTX *tmp_ctx; ++ ++ tmp_ctx = talloc_new(NULL); ++ if (tmp_ctx == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n"); ++ return ENOMEM; ++ } ++ ++ local_groups_base_dn = talloc_asprintf(tmp_ctx, SYSDB_TMPL_GROUP_BASE, ++ dom->name); ++ if (local_groups_base_dn == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ if (gr->parents_count != 0) { ++ /* Store the parents if needed */ ++ ret = sdap_nested_groups_store(sysdb, dom, opts, ++ gr->ldap_parents, gr->parents_count); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_MINOR_FAILURE, "Could not save groups [%d]: %s\n", ++ ret, strerror(ret)); ++ goto done; ++ } ++ ++ ret = sysdb_attrs_primary_fqdn_list(dom, tmp_ctx, ++ gr->ldap_parents, gr->parents_count, ++ opts->group_map[SDAP_AT_GROUP_NAME].name, ++ &groupnamelist); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_primary_fqdn_list failed.\n"); ++ goto done; ++ } ++ } ++ ++ ret = sysdb_attrs_get_string(gr->group, SYSDB_NAME, &sysdb_name); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "sysdb_attrs_get_string failed to get SYSDB_NAME, " ++ "skipping.\n"); ++ goto done; ++ } ++ ++ ret = sysdb_attrs_get_string(gr->group, SYSDB_OBJECTCLASS, &class); ++ if (ret != EOK) { ++ /* If objectclass is missing gr->group is a nested parent found during ++ * the nested group lookup. It might not already stored in the cache. ++ */ ++ DEBUG(SSSDBG_TRACE_LIBS, ++ "sysdb_attrs_get_string failed to get SYSDB_OBJECTCLASS " ++ "for [%s], assuming group.\n", sysdb_name); ++ ++ /* make sure group exists in cache */ ++ groups[0]= gr->group; ++ ret = sdap_nested_groups_store(sysdb, dom, opts, groups, 1); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_MINOR_FAILURE, "Could not save groups [%d]: %s\n", ++ ret, strerror(ret)); ++ goto done; ++ } ++ ++ /* Since the object is coming from LDAP it cannot have the internal ++ * fully-qualified name, so we can expand it unconditionally. */ ++ group_name = NULL; ++ ret = sysdb_attrs_primary_name(dom->sysdb, gr->group, ++ opts->group_map[SDAP_AT_GROUP_NAME].name, ++ &group_name); ++ if (ret != EOK || group_name == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "Could not determine primary name\n"); ++ group_name = sysdb_name; ++ } ++ ++ group_name = sss_create_internal_fqname(tmp_ctx, group_name, ++ dom->name); ++ if (group_name != NULL) { ++ sysdb_name = group_name; ++ } ++ ++ type = SYSDB_MEMBER_GROUP; ++ } else { ++ if (class != NULL && strcmp(class, SYSDB_USER_CLASS) == 0) { ++ type = SYSDB_MEMBER_USER; ++ } else { ++ type = SYSDB_MEMBER_GROUP; ++ } ++ } ++ ++ /* We need to get the cached list of groups form the local domain the ++ * object is a member of to compare them with the current list just ++ * retrieved (groupnamelist). Even if this list is empty we have to ++ * proceed because the membership might have been removed recently on the ++ * server. */ ++ ++ obj_dom = find_domain_by_object_name(get_domains_head(dom), ++ sysdb_name); ++ if (obj_dom == NULL) { ++ obj_dom = dom; ++ DEBUG(SSSDBG_OP_FAILURE, "Cannot find domain for [%s], " ++ "trying with local domain [%s].\n", ++ sysdb_name, obj_dom->name); ++ } ++ ++ ret = sysdb_get_direct_parents(tmp_ctx, obj_dom, dom, type, sysdb_name, ++ &cached_local_parents); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE,"sysdb_get_direct_parents failed.\n"); ++ goto done; ++ } ++ ++ if (cached_local_parents != NULL && cached_local_parents[0] == NULL) { ++ talloc_zfree(cached_local_parents); ++ } ++ ++ if (DEBUG_IS_SET(SSSDBG_TRACE_ALL)) { ++ if (cached_local_parents != NULL) { ++ for (c = 0; cached_local_parents[c] != NULL; c++) { ++ DEBUG(SSSDBG_TRACE_ALL, "[%s] cached_local_parents [%s].\n", ++ sysdb_name, cached_local_parents[c]); ++ } ++ } ++ ++ if (groupnamelist != NULL) { ++ for (c = 0; groupnamelist[c] != NULL; c++) { ++ DEBUG(SSSDBG_TRACE_ALL, "[%s] groupnamelist [%s].\n", ++ sysdb_name, groupnamelist[c]); ++ } ++ } ++ } ++ ++ ret = diff_string_lists(tmp_ctx, cached_local_parents, groupnamelist, ++ &del_list, &add_list, NULL); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, "diff_string_lists failed.\n"); ++ goto done; ++ } ++ ++ if (DEBUG_IS_SET(SSSDBG_TRACE_ALL)) { ++ if (add_list != NULL) { ++ for (c = 0; add_list[c] != NULL; c++) { ++ DEBUG(SSSDBG_TRACE_ALL, "add: [%s] will be member of [%s].\n", ++ sysdb_name, add_list[c]); ++ } ++ } ++ if (del_list != NULL) { ++ for (c = 0; del_list[c] != NULL; c++) { ++ DEBUG(SSSDBG_TRACE_ALL, "del: [%s] was member of [%s].\n", ++ sysdb_name, del_list[c]); ++ } ++ } ++ } ++ ++ *_type = type; ++ *_sysdb_name = talloc_steal(mem_ctx, sysdb_name); ++ *_add_list = talloc_steal(mem_ctx, groupnamelist); ++ *_del_list = talloc_steal(mem_ctx, del_list); ++ ret = EOK; ++ ++done: ++ talloc_free(tmp_ctx); ++ ++ return ret; ++} ++ ++static void sdap_ad_get_domain_local_groups_done(struct tevent_req *subreq) ++{ ++ ++ struct tevent_req *req = tevent_req_callback_data(subreq, ++ struct tevent_req); ++ struct sdap_ad_get_domain_local_groups_state *state = tevent_req_data(req, ++ struct sdap_ad_get_domain_local_groups_state); ++ int ret; ++ int hret; ++ unsigned long count; ++ hash_value_t *values = NULL; ++ struct sdap_nested_group *gr; ++ size_t c; ++ const char *sysdb_name = NULL; ++ enum sysdb_member_type type; ++ char **add_list = NULL; ++ char **del_list = NULL; ++ ++ ret = rfc2307bis_nested_groups_recv(subreq); ++ talloc_zfree(subreq); ++ if (ret != EOK) { ++ tevent_req_error(req, ret); ++ return; ++ } ++ ++ hret = hash_values(state->group_hash, &count, &values); ++ if (hret != HASH_SUCCESS) { ++ DEBUG(SSSDBG_OP_FAILURE, "hash_values failed.\n"); ++ ret = EIO; ++ goto done; ++ } ++ ++ for (c = 0; c < count; c++) { ++ gr = talloc_get_type(values[c].ptr, ++ struct sdap_nested_group); ++ ++ /* The values from the hash are either user or group objects returned ++ * by sysdb_initgroups() which where used to start the request or ++ * nested parents found during the request. The nested parents contain ++ * the processed LDAP data and can be identified by a missing ++ * objectclass attribute. */ ++ ret = sdap_ad_get_domain_local_groups_parse_parents(state, gr, ++ state->dom, ++ state->sysdb, ++ state->opts, ++ &sysdb_name, ++ &type, ++ &add_list, ++ &del_list); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "sdap_ad_get_domain_local_groups_parse_parents failed.\n"); ++ continue; ++ } ++ ++ if ((add_list == NULL && del_list == NULL) ++ || (add_list == NULL && del_list != NULL && del_list[0] == NULL) ++ || (add_list != NULL && add_list[0] == NULL && del_list == NULL) ++ || (add_list != NULL && add_list[0] == NULL ++ && del_list != NULL && del_list[0] == NULL) ) { ++ continue; ++ } ++ ++ DEBUG(SSSDBG_TRACE_INTERNAL, "Updating domain local memberships for %s\n", ++ sysdb_name); ++ ret = sysdb_update_members(state->dom, sysdb_name, type, ++ (const char *const *) add_list, ++ (const char *const *) del_list); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, "sysdb_update_members failed.\n"); ++ goto done; ++ } ++ } ++ ++ ret = EOK; ++done: ++ talloc_zfree(values); ++ ++ if (ret == EOK) { ++ tevent_req_done(req); ++ } else { ++ tevent_req_error(req, ret); ++ } ++ ++ return; ++} ++ ++errno_t sdap_ad_get_domain_local_groups_recv(struct tevent_req *req) ++{ ++ TEVENT_REQ_RETURN_ON_ERROR(req); ++ return EOK; ++} ++ + struct sdap_ad_tokengroups_initgroups_state { + bool use_id_mapping; + struct sss_domain_info *domain; +diff --git a/src/providers/ldap/sdap_async_private.h b/src/providers/ldap/sdap_async_private.h +index 4af4f7144d8855e4ed705f6a64e0a7818bc0b9a9..266bc03115e2bdd6a283f5f7da565fd00d3a77be 100644 +--- a/src/providers/ldap/sdap_async_private.h ++++ b/src/providers/ldap/sdap_async_private.h +@@ -173,4 +173,14 @@ errno_t sdap_nested_groups_store(struct sysdb_ctx *sysdb, + struct sysdb_attrs **groups, + unsigned long count); + ++struct tevent_req * ++sdap_ad_get_domain_local_groups_send(TALLOC_CTX *mem_ctx, ++ struct tevent_context *ev, ++ struct sdap_domain *local_sdom, ++ struct sdap_options *opts, ++ struct sysdb_ctx *sysdb, ++ struct sss_domain_info *dom, ++ struct sysdb_attrs **groups, ++ size_t num_groups); ++errno_t sdap_ad_get_domain_local_groups_recv(struct tevent_req *req); + #endif /* _SDAP_ASYNC_PRIVATE_H_ */ +-- +2.7.4 + diff --git a/SOURCES/0147-IPA-Initialize-a-boolean-control-value.patch b/SOURCES/0147-IPA-Initialize-a-boolean-control-value.patch new file mode 100644 index 0000000..7a6ee0e --- /dev/null +++ b/SOURCES/0147-IPA-Initialize-a-boolean-control-value.patch @@ -0,0 +1,60 @@ +From ffe5898f9588ba4ec3258807d377a82e52c38c67 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Tue, 4 Oct 2016 10:45:43 +0200 +Subject: [PATCH 147/149] IPA: Initialize a boolean control value +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +without this patch, valgrind was reporting: +==30955== Conditional jump or move depends on uninitialised value(s) +==30955== at 0xDBBACC3: ipa_subdomains_slave_search_done (ipa_subdomains.c:1111) +==30955== by 0xE73B34D: sdap_search_bases_ex_done (sdap_ops.c:222) +==30955== by 0xE6FFA98: sdap_get_generic_done (sdap_async.c:1872) +==30955== by 0xE6FF4E2: generic_ext_search_handler (sdap_async.c:1689) +==30955== by 0xE6FF840: sdap_get_and_parse_generic_done (sdap_async.c:1797) +==30955== by 0xE6FEFB5: sdap_get_generic_op_finished (sdap_async.c:1579) +==30955== by 0xE6FB1D2: sdap_process_message (sdap_async.c:353) +==30955== by 0xE6FAD51: sdap_process_result (sdap_async.c:197) +==30955== by 0xE6FAA14: sdap_ldap_next_result (sdap_async.c:145) +==30955== by 0x8E157FF: tevent_common_loop_timer_delay (tevent_timed.c:341) +==30955== by 0x8E16809: epoll_event_loop_once (tevent_epoll.c:911) +==30955== by 0x8E14F09: std_event_loop_once (tevent_standard.c:114) +==30955== + +Resolves: +https://fedorahosted.org/sssd/ticket/3213 + +Reviewed-by: Fabiano FidĂȘncio +--- + src/providers/ipa/ipa_subdomains.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c +index 4e5bceb8c761bf4476928168d620baf2beb62ad5..d02d2d5c05904c54c5e1997aece82f940b7334ee 100644 +--- a/src/providers/ipa/ipa_subdomains.c ++++ b/src/providers/ipa/ipa_subdomains.c +@@ -482,6 +482,11 @@ static errno_t ipa_subdomains_refresh(struct ipa_subdomains_ctx *ctx, + memset(handled, 0, sizeof(bool) * count); + h = 0; + ++ if (changes == NULL) { ++ return EINVAL; ++ } ++ *changes = false; ++ + /* check existing subdomains */ + for (dom = get_next_domain(parent, SSS_GND_DESCEND); + dom && IS_SUBDOMAIN(dom); /* if we get back to a parent, stop */ +@@ -1084,7 +1089,7 @@ static void ipa_subdomains_slave_search_done(struct tevent_req *subreq) + struct tevent_req *req; + struct sysdb_attrs **reply; + size_t reply_count; +- bool has_changes; ++ bool has_changes = false; + errno_t ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); +-- +2.7.4 + diff --git a/SPECS/sssd.spec b/SPECS/sssd.spec index 370e6d7..39bed2c 100644 --- a/SPECS/sssd.spec +++ b/SPECS/sssd.spec @@ -33,7 +33,7 @@ Name: sssd Version: 1.14.0 -Release: 43%{?dist} +Release: 43%{?dist}.4 Group: Applications/System Summary: System Security Services Daemon License: GPLv3+ @@ -184,6 +184,10 @@ Patch0140: 0140-TEST-Add-regression-test-for-ticket-3179.patch Patch0141: 0141-p11-only-set-PKCS11_LOGIN_TOKEN_NAME-if-gdm-smartcar.patch Patch0142: 0142-p11-return-a-fully-qualified-name.patch Patch0143: 0143-pam_sss-check-PKCS11_LOGIN_TOKEN_NAME.patch +Patch0144: 0144-sysdb-add-parent_dom-to-sysdb_get_direct_parents.patch +Patch0145: 0145-sdap-make-some-nested-group-related-calls-public.patch +Patch0146: 0146-LDAP-AD-resolve-domain-local-groups-for-remote-users.patch +Patch0147: 0147-IPA-Initialize-a-boolean-control-value.patch #This patch should not be removed in RHEL-7 Patch999: 0999-NOUPSTREAM-Default-to-root-if-sssd-user-is-not-spec @@ -1178,6 +1182,22 @@ fi /usr/bin/rm -f /var/tmp/sssd.upgrade || : %changelog +* Mon Nov 14 2016 Jakub Hrozek - 1.14.0-43.4 +- Revert the fix for ignoring sudoUser case as it breaks processing + of rules that completely lack a sudoUser attribute +- Related: rhbz#1392946 - sudo: ignore case on case insensitive domains + +* Wed Nov 9 2016 Jakub Hrozek - 1.14.0-43.3 +- Resolves: rhbz#1392946 - sudo: ignore case on case insensitive domains + +* Tue Nov 8 2016 Jakub Hrozek - 1.14.0-43.2 +- Resolves: rhbz#1392893 - IPA: Uninitialized variable during subdomain check + +* Mon Nov 7 2016 Jakub Hrozek - 1.14.0-43.1 +- Resolves: rhbz#1392896 - AD provider: SSSD does not retrieve a domain-local + group with the AD provider when following AGGUDLP + group structure across domains + * Tue Sep 20 2016 Jakub Hrozek - 1.14.0-43 - Resolves: rhbz#1376831 - sssd-common is missing dependency on sssd-sudo