diff --git a/SOURCES/0062-UTIL-find_domain_by_object_name_ex-changed-log-level.patch b/SOURCES/0062-UTIL-find_domain_by_object_name_ex-changed-log-level.patch new file mode 100644 index 0000000..708327b --- /dev/null +++ b/SOURCES/0062-UTIL-find_domain_by_object_name_ex-changed-log-level.patch @@ -0,0 +1,36 @@ +From ba06302d262aa3571620455fafadb43aaa93139e Mon Sep 17 00:00:00 2001 +From: Alexey Tikhonov +Date: Tue, 15 Dec 2020 18:47:25 +0100 +Subject: [PATCH] UTIL: find_domain_by_object_name_ex() changed log level +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +It's up to user of this function to judge if fail to parse fqname is +a critical error. + +Reviewed-by: Pawel Polawski +Reviewed-by: Sumit Bose +(cherry picked from commit bd2f38abe95645b9b16b12d12dac6008b0d2a03b) + +Reviewed-by: Tomáš Halman +--- + src/util/domain_info_utils.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c +index 71dfcba02..5a374074b 100644 +--- a/src/util/domain_info_utils.c ++++ b/src/util/domain_info_utils.c +@@ -207,7 +207,7 @@ find_domain_by_object_name_ex(struct sss_domain_info *domain, + ret = sss_parse_internal_fqname(tmp_ctx, object_name, + NULL, &domainname); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse name '%s' [%d]: %s\n", ++ DEBUG(SSSDBG_MINOR_FAILURE, "Unable to parse name '%s' [%d]: %s\n", + object_name, ret, sss_strerror(ret)); + goto done; + } +-- +2.26.3 + diff --git a/SOURCES/0063-sudo-do-not-search-by-low-usn-value-to-improve-perfo.patch b/SOURCES/0063-sudo-do-not-search-by-low-usn-value-to-improve-perfo.patch new file mode 100644 index 0000000..cfd972d --- /dev/null +++ b/SOURCES/0063-sudo-do-not-search-by-low-usn-value-to-improve-perfo.patch @@ -0,0 +1,122 @@ +From 73f35e5e6836c3d63cfdc4d85dfbfed99f0bcf5a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Fri, 29 Jan 2021 12:41:28 +0100 +Subject: [PATCH] sudo: do not search by low usn value to improve performance + +This is a follow up on these two commits. + +- 819d70ef6e6fa0e736ebd60a7f8a26f672927d57 +- 6815844daa7701c76e31addbbdff74656cd30bea + +The first one improved the search filter little bit to achieve better +performance, however it also changed the behavior: we started to search +for `usn >= 1` in the filter if no usn number was known. + +This caused issues on OpenLDAP server which was fixed by the second patch. +However, the fix was wrong and searching by this meaningfully low number +can cause performance issues depending on how the filter is optimized and +evaluated on the server. + +Now we omit the usn attribute from the filter if there is no meaningful value. + +How to test: +1. Setup LDAP with no sudo rules defined +2. Make sure that the LDAP server does not support USN or use the following diff + to enforce modifyTimestamp (last USN is always available from rootDSE) +```diff + +Reviewed-by: Alexey Tikhonov +(cherry picked from commit b100efbfabd96dcfb2825777b75b9a9dfaacb937) +--- + src/providers/ldap/sdap.c | 4 ++-- + src/providers/ldap/sdap_sudo_refresh.c | 6 ++++-- + src/providers/ldap/sdap_sudo_shared.c | 21 ++++++--------------- + 3 files changed, 12 insertions(+), 19 deletions(-) + +diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c +index a1a00df56..0413930bc 100644 +--- a/src/providers/ldap/sdap.c ++++ b/src/providers/ldap/sdap.c +@@ -1322,7 +1322,7 @@ int sdap_get_server_opts_from_rootdse(TALLOC_CTX *memctx, + last_usn_name = opts->gen_map[SDAP_AT_LAST_USN].name; + entry_usn_name = opts->gen_map[SDAP_AT_ENTRY_USN].name; + if (rootdse) { +- if (last_usn_name) { ++ if (false) { + ret = sysdb_attrs_get_string(rootdse, + last_usn_name, &last_usn_value); + if (ret != EOK) { +@@ -1431,7 +1431,7 @@ int sdap_get_server_opts_from_rootdse(TALLOC_CTX *memctx, + } + } + +- if (!last_usn_name) { ++ if (true) { + DEBUG(SSSDBG_FUNC_DATA, + "No known USN scheme is supported by this server!\n"); + if (!entry_usn_name) { +diff --git a/src/providers/ldap/sdap_sudo_refresh.c b/src/providers/ldap/sdap_sudo_refresh.c +index 5c72c6ec5..fd5deeb7a 100644 +--- a/src/providers/ldap/sdap_sudo_refresh.c ++++ b/src/providers/ldap/sdap_sudo_refresh.c +@@ -181,8 +181,10 @@ struct tevent_req *sdap_sudo_smart_refresh_send(TALLOC_CTX *mem_ctx, + state->sysdb = id_ctx->be->domain->sysdb; + + /* Download all rules from LDAP that are newer than usn */ +- if (srv_opts == NULL || srv_opts->max_sudo_value == 0) { +- DEBUG(SSSDBG_TRACE_FUNC, "USN value is unknown, assuming zero.\n"); ++ if (srv_opts == NULL || srv_opts->max_sudo_value == NULL ++ || strcmp(srv_opts->max_sudo_value, "0") == 0) { ++ DEBUG(SSSDBG_TRACE_FUNC, "USN value is unknown, assuming zero and " ++ "omitting it from the filter.\n"); + usn = "0"; + search_filter = talloc_asprintf(state, "(%s=%s)", + map[SDAP_AT_SUDO_OC].name, +diff --git a/src/providers/ldap/sdap_sudo_shared.c b/src/providers/ldap/sdap_sudo_shared.c +index bd3a24da0..5f6afb1ac 100644 +--- a/src/providers/ldap/sdap_sudo_shared.c ++++ b/src/providers/ldap/sdap_sudo_shared.c +@@ -127,25 +127,17 @@ sdap_sudo_ptask_setup_generic(struct be_ctx *be_ctx, + static char * + sdap_sudo_new_usn(TALLOC_CTX *mem_ctx, + unsigned long usn, +- const char *leftover, +- bool supports_usn) ++ const char *leftover) + { + const char *str = leftover == NULL ? "" : leftover; + char *newusn; + +- /* This is a fresh start and server uses modifyTimestamp. We need to +- * provide proper datetime value. */ +- if (!supports_usn && usn == 0) { +- newusn = talloc_strdup(mem_ctx, "00000101000000Z"); +- if (newusn == NULL) { +- DEBUG(SSSDBG_MINOR_FAILURE, "Unable to change USN value (OOM)!\n"); +- return NULL; +- } +- +- return newusn; ++ /* Current largest USN is unknown so we keep "0" to indicate it. */ ++ if (usn == 0) { ++ return talloc_strdup(mem_ctx, "0"); + } + +- /* We increment USN number so that we can later use simplify filter ++ /* We increment USN number so that we can later use simplified filter + * (just usn >= last+1 instead of usn >= last && usn != last). + */ + usn++; +@@ -217,8 +209,7 @@ sdap_sudo_set_usn(struct sdap_server_opts *srv_opts, + srv_opts->last_usn = usn_number; + } + +- newusn = sdap_sudo_new_usn(srv_opts, srv_opts->last_usn, timezone, +- srv_opts->supports_usn); ++ newusn = sdap_sudo_new_usn(srv_opts, srv_opts->last_usn, timezone); + if (newusn == NULL) { + return; + } +-- +2.26.3 + diff --git a/SOURCES/0064-ldap-fix-modifytimestamp-debugging-leftovers.patch b/SOURCES/0064-ldap-fix-modifytimestamp-debugging-leftovers.patch new file mode 100644 index 0000000..e985de6 --- /dev/null +++ b/SOURCES/0064-ldap-fix-modifytimestamp-debugging-leftovers.patch @@ -0,0 +1,36 @@ +From b816fa19ec6be3c5eb183d1caa03f0153538e2ac Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Fri, 12 Feb 2021 15:30:59 +0100 +Subject: [PATCH] ldap: fix modifytimestamp debugging leftovers + +Reviewed-by: Alexey Tikhonov +(cherry picked from commit 75343ff575f05a69750a6482de9abc29d85100bf) +--- + src/providers/ldap/sdap.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c +index 0413930bc..a1a00df56 100644 +--- a/src/providers/ldap/sdap.c ++++ b/src/providers/ldap/sdap.c +@@ -1322,7 +1322,7 @@ int sdap_get_server_opts_from_rootdse(TALLOC_CTX *memctx, + last_usn_name = opts->gen_map[SDAP_AT_LAST_USN].name; + entry_usn_name = opts->gen_map[SDAP_AT_ENTRY_USN].name; + if (rootdse) { +- if (false) { ++ if (last_usn_name) { + ret = sysdb_attrs_get_string(rootdse, + last_usn_name, &last_usn_value); + if (ret != EOK) { +@@ -1431,7 +1431,7 @@ int sdap_get_server_opts_from_rootdse(TALLOC_CTX *memctx, + } + } + +- if (true) { ++ if (!last_usn_name) { + DEBUG(SSSDBG_FUNC_DATA, + "No known USN scheme is supported by this server!\n"); + if (!entry_usn_name) { +-- +2.26.3 + diff --git a/SOURCES/0065-sss_domain_info-add-not_found_counter.patch b/SOURCES/0065-sss_domain_info-add-not_found_counter.patch new file mode 100644 index 0000000..906cf28 --- /dev/null +++ b/SOURCES/0065-sss_domain_info-add-not_found_counter.patch @@ -0,0 +1,67 @@ +From f511e73867f22fff9d0867b07013accb4f44cb1f Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Wed, 14 Apr 2021 17:22:06 +0200 +Subject: [PATCH 65/66] sss_domain_info: add not_found_counter +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This new counter should be used to track how often a domain could not be +found while discovering the environment so that it can be deleted after +a number of failed attempts. + +Resolves: https://github.com/SSSD/sssd/issues/5528 + +Reviewed-by: Pavel Březina +(cherry picked from commit 5d65411f1aa16af929ae2271ee4d3d9101728a67 with changes) + +Reviewed-by: Pavel Březina +--- + src/confdb/confdb.c | 1 + + src/confdb/confdb.h | 4 ++++ + src/db/sysdb_subdomains.c | 2 ++ + 3 files changed, 7 insertions(+) + +diff --git a/src/confdb/confdb.c b/src/confdb/confdb.c +index 97de6d3b1..a33f352e7 100644 +--- a/src/confdb/confdb.c ++++ b/src/confdb/confdb.c +@@ -1474,6 +1474,7 @@ static int confdb_get_domain_internal(struct confdb_ctx *cdb, + domain->view_name = NULL; + + domain->state = DOM_ACTIVE; ++ domain->not_found_counter = 0; + + *_domain = domain; + ret = EOK; +diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h +index b0d52ba49..a1ac676a6 100644 +--- a/src/confdb/confdb.h ++++ b/src/confdb/confdb.h +@@ -406,6 +406,10 @@ struct sss_domain_info { + /* Do not use the _output_fqnames property directly in new code, but rather + * use sss_domain_info_{get,set}_output_fqnames(). */ + bool output_fqnames; ++ ++ /* Counts how often the domain was not found during a refresh of the ++ * domain list */ ++ size_t not_found_counter; + }; + + /** +diff --git a/src/db/sysdb_subdomains.c b/src/db/sysdb_subdomains.c +index ee3c7f1aa..cbb11342e 100644 +--- a/src/db/sysdb_subdomains.c ++++ b/src/db/sysdb_subdomains.c +@@ -171,6 +171,8 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx, + dom->homedir_substr = parent->homedir_substr; + dom->override_gid = parent->override_gid; + ++ dom->not_found_counter = 0; ++ + if (parent->sysdb == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "Missing sysdb context in parent domain.\n"); + goto fail; +-- +2.26.3 + diff --git a/SOURCES/0066-AD-read-trusted-domains-from-local-domain-as-well.patch b/SOURCES/0066-AD-read-trusted-domains-from-local-domain-as-well.patch new file mode 100644 index 0000000..c735dc4 --- /dev/null +++ b/SOURCES/0066-AD-read-trusted-domains-from-local-domain-as-well.patch @@ -0,0 +1,244 @@ +From 2519d5ea3757862bebc17d73d74c7e5c57bdc815 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Tue, 16 Feb 2021 14:30:55 +0100 +Subject: [PATCH 66/66] AD: read trusted domains from local domain as well +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Currently SSSD only uses information stored in a domain controller of +the forest root domain to get the names of other trusted domains in the +forest. Depending on how the forest was created the forest root might +not have LDAP objects for all domains in the forest. It looks like a +typical case are child domains of other domains in the forest. + +As a start SSSD can now include trusted domains stored in the LDAP tree +of a local domain controller as well. In a long run it would make sense +to allow SSSD to explicitly search for domain by looking up DNS entries +and checking a potential domain controller with a CLDAP ping. + +Resolves: https://github.com/SSSD/sssd/issues/5528 + +:feature: Besides trusted domains known by the forest root, trusted + domains known by the local domain are used as well. + +Reviewed-by: Pavel Březina +(cherry picked from commit 95adf488f94f5968f6cfba9e3bef74c07c02ccff) + +Reviewed-by: Pavel Březina +--- + src/providers/ad/ad_subdomains.c | 105 +++++++++++++++++++++++++------ + 1 file changed, 86 insertions(+), 19 deletions(-) + +diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c +index ba4efe975..16aecbc64 100644 +--- a/src/providers/ad/ad_subdomains.c ++++ b/src/providers/ad/ad_subdomains.c +@@ -45,6 +45,7 @@ + #define AD_AT_TRUST_TYPE "trustType" + #define AD_AT_TRUST_PARTNER "trustPartner" + #define AD_AT_TRUST_ATTRS "trustAttributes" ++#define AD_AT_DOMAIN_NAME "cn" + + /* trustType=2 denotes uplevel (NT5 and later) trusted domains. See + * http://msdn.microsoft.com/en-us/library/windows/desktop/ms680342%28v=vs.85%29.aspx +@@ -56,7 +57,6 @@ + */ + #define SLAVE_DOMAIN_FILTER_BASE "(objectclass=trustedDomain)(trustType=2)(!(msDS-TrustForestTrustInfo=*))" + #define SLAVE_DOMAIN_FILTER "(&"SLAVE_DOMAIN_FILTER_BASE")" +-#define FOREST_ROOT_FILTER_FMT "(&"SLAVE_DOMAIN_FILTER_BASE"(cn=%s))" + + /* Attributes of schema objects. See e.g. + * https://docs.microsoft.com/en-us/windows/desktop/AD/characteristics-of-attributes +@@ -646,6 +646,10 @@ done: + return ret; + } + ++/* How many times we keep a domain not found during searches before it will be ++ * removed. */ ++#define MAX_NOT_FOUND 6 ++ + static errno_t ad_subdomains_refresh(struct be_ctx *be_ctx, + struct sdap_idmap_ctx *idmap_ctx, + struct sdap_options *opts, +@@ -706,6 +710,25 @@ static errno_t ad_subdomains_refresh(struct be_ctx *be_ctx, + } + + if (c >= num_subdomains) { ++ DEBUG(SSSDBG_CONF_SETTINGS, "Domain [%s] not in current list.\n", ++ dom->name); ++ /* Since the forest root might not have trustedDomain objects for ++ * each domain in the forest, especially e.g. for child-domains of ++ * child-domains, we cannot reliable say if a domain is still ++ * present or not. ++ * Maybe it would work to check the crossRef objects in ++ * CN=Partitions,CN=Configuration as well to understand if a ++ * domain is still known in the forest or not. ++ * For the time being we use a counter, if a domain was not found ++ * after multiple attempts it will be deleted. */ ++ ++ if (dom->not_found_counter++ < MAX_NOT_FOUND) { ++ DEBUG(SSSDBG_TRACE_ALL, ++ "Domain [%s] was not found [%zu] times.\n", dom->name, ++ dom->not_found_counter); ++ continue; ++ } ++ + /* ok this subdomain does not exist anymore, let's clean up */ + sss_domain_set_state(dom, DOM_DISABLED); + +@@ -743,6 +766,7 @@ static errno_t ad_subdomains_refresh(struct be_ctx *be_ctx, + /* terminate all requests for this subdomain so we can free it */ + dp_terminate_domain_requests(be_ctx->provider, dom->name); + talloc_zfree(sdom); ++ + } else { + /* ok let's try to update it */ + ret = ad_subdom_enumerates(domain, subdomains[c], &enumerate); +@@ -750,6 +774,7 @@ static errno_t ad_subdomains_refresh(struct be_ctx *be_ctx, + goto done; + } + ++ dom->not_found_counter = 0; + ret = ad_subdom_store(be_ctx->cdb, idmap_ctx, domain, + subdomains[c], enumerate); + if (ret) { +@@ -1310,10 +1335,9 @@ ad_get_root_domain_send(TALLOC_CTX *mem_ctx, + struct tevent_req *req; + struct sdap_options *opts; + errno_t ret; +- const char *filter; + const char *attrs[] = { AD_AT_FLATNAME, AD_AT_TRUST_PARTNER, + AD_AT_SID, AD_AT_TRUST_TYPE, +- AD_AT_TRUST_ATTRS, NULL }; ++ AD_AT_TRUST_ATTRS, AD_AT_DOMAIN_NAME, NULL }; + + req = tevent_req_create(mem_ctx, &state, struct ad_get_root_domain_state); + if (req == NULL) { +@@ -1338,15 +1362,10 @@ ad_get_root_domain_send(TALLOC_CTX *mem_ctx, + state->domain = domain; + state->forest = forest; + +- filter = talloc_asprintf(state, FOREST_ROOT_FILTER_FMT, forest); +- if (filter == NULL) { +- ret = ENOMEM; +- goto immediately; +- } +- + subreq = sdap_search_bases_return_first_send(state, ev, opts, sh, + opts->sdom->search_bases, +- NULL, false, 0, filter, attrs, ++ NULL, false, 0, ++ SLAVE_DOMAIN_FILTER, attrs, + NULL); + if (subreq == NULL) { + ret = ENOMEM; +@@ -1368,11 +1387,33 @@ immediately: + return req; + } + ++static struct sysdb_attrs *find_domain(size_t count, struct sysdb_attrs **reply, ++ const char *dom_name) ++{ ++ size_t c; ++ const char *name; ++ int ret; ++ ++ for (c = 0; c < count; c++) { ++ ret = sysdb_attrs_get_string(reply[c], AD_AT_DOMAIN_NAME, &name); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, "Failed to find domain name, skipping"); ++ continue; ++ } ++ if (strcasecmp(name, dom_name) == 0) { ++ return reply[c]; ++ } ++ } ++ ++ return NULL; ++} ++ + static void ad_get_root_domain_done(struct tevent_req *subreq) + { + struct tevent_req *req; + struct ad_get_root_domain_state *state; + errno_t ret; ++ bool has_changes = false; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct ad_get_root_domain_state); +@@ -1387,7 +1428,37 @@ static void ad_get_root_domain_done(struct tevent_req *subreq) + goto done; + } + +- if (state->reply_count == 0) { ++ find_domain(state->reply_count, state->reply, state->forest); ++ ++ if (state->reply_count == 0 ++ || find_domain(state->reply_count, state->reply, ++ state->forest) == NULL) { ++ ++ if (state->reply_count > 0) { ++ /* refresh the other domains we have found before checking forest ++ * root */ ++ ret = ad_subdomains_refresh(state->be_ctx, state->idmap_ctx, ++ state->opts, ++ state->reply, state->reply_count, false, ++ &state->sd_ctx->last_refreshed, ++ &has_changes); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "ad_subdomains_refresh failed [%d]: %s\n", ++ ret, sss_strerror(ret)); ++ goto done; ++ } ++ ++ if (has_changes) { ++ ret = ad_subdom_reinit(state->sd_ctx); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "Could not reinitialize subdomains\n"); ++ goto done; ++ } ++ } ++ } ++ + DEBUG(SSSDBG_OP_FAILURE, + "No information provided for root domain, trying directly.\n"); + subreq = ad_check_domain_send(state, state->ev, state->be_ctx, +@@ -1400,11 +1471,6 @@ static void ad_get_root_domain_done(struct tevent_req *subreq) + } + tevent_req_set_callback(subreq, ad_check_root_domain_done, req); + return; +- } else if (state->reply_count > 1) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Multiple results for root domain search, " +- "domain list might be incomplete!\n"); +- ret = ERR_MALFORMED_ENTRY; +- goto done; + } + + ret = ad_get_root_domain_refresh(state); +@@ -1522,7 +1588,7 @@ ad_get_root_domain_refresh(struct ad_get_root_domain_state *state) + errno_t ret; + + ret = ad_subdomains_refresh(state->be_ctx, state->idmap_ctx, state->opts, +- state->reply, state->reply_count, true, ++ state->reply, state->reply_count, false, + &state->sd_ctx->last_refreshed, + &has_changes); + if (ret != EOK) { +@@ -1539,8 +1605,9 @@ ad_get_root_domain_refresh(struct ad_get_root_domain_state *state) + } + } + +- state->root_domain_attrs = state->reply[0]; +- root_domain = ads_get_root_domain(state->be_ctx, state->reply[0]); ++ state->root_domain_attrs = find_domain(state->reply_count, state->reply, ++ state->forest); ++ root_domain = ads_get_root_domain(state->be_ctx, state->root_domain_attrs); + if (root_domain == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "Could not find the root domain\n"); + ret = EFAULT; +-- +2.26.3 + diff --git a/SOURCES/0067-negcache-use-right-domain-in-nss_protocol_fill_initg.patch b/SOURCES/0067-negcache-use-right-domain-in-nss_protocol_fill_initg.patch new file mode 100644 index 0000000..3a4f404 --- /dev/null +++ b/SOURCES/0067-negcache-use-right-domain-in-nss_protocol_fill_initg.patch @@ -0,0 +1,107 @@ +From 48f27f74c9a9d5aebf8d2be941dfb282578ba9ba Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Fri, 12 Mar 2021 14:38:54 +0100 +Subject: [PATCH] negcache: use right domain in nss_protocol_fill_initgr() + +When checking if a group returned by an initgroups request is filtered +in the negative cache the domain of the user was used. This does not +work reliable if the user can be a member of groups from multiple +domains. + +With this patch th domain the group belongs to is determined and used +while checking the negative cache. + +Resolves: https://github.com/SSSD/sssd/issues/5534 +(cherry picked from commit 231d1118727b989a4af9911a45a465912fe659d6 with changes) + +Reviewed-by: Alexey Tikhonov +--- + src/db/sysdb.c | 22 ++++++++++++++++++++++ + src/db/sysdb.h | 7 +++++++ + src/responder/nss/nss_protocol_grent.c | 8 +++++--- + 3 files changed, 34 insertions(+), 3 deletions(-) + +diff --git a/src/db/sysdb.c b/src/db/sysdb.c +index 279bd5839..f9929c7ba 100644 +--- a/src/db/sysdb.c ++++ b/src/db/sysdb.c +@@ -1978,3 +1978,25 @@ done: + talloc_free(tmp_ctx); + return differs; + } ++ ++struct sss_domain_info *find_domain_by_msg(struct sss_domain_info *dom, ++ struct ldb_message *msg) ++{ ++ const char *name; ++ struct sss_domain_info *obj_dom = NULL; ++ ++ name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL); ++ if (name == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "Object does not have a name attribute.\n"); ++ return dom; ++ } ++ ++ obj_dom = find_domain_by_object_name(get_domains_head(dom), name); ++ if (obj_dom == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "No domain found for [%s].\n", name); ++ return dom; ++ } ++ ++ return obj_dom; ++} +diff --git a/src/db/sysdb.h b/src/db/sysdb.h +index 679763bad..d47099eff 100644 +--- a/src/db/sysdb.h ++++ b/src/db/sysdb.h +@@ -1505,4 +1505,11 @@ errno_t sysdb_handle_original_uuid(const char *orig_name, + struct sysdb_attrs *dest_attrs, + const char *dest_name); + ++/* Try to detect the object domain from the object's SYSDB_NAME attribute and ++ * return the matching sss_domain_info. This should work reliable with user ++ * and group objects since fully-qualified names are used here. If the proper ++ * domain cannot be detected the given domain is returned. */ ++struct sss_domain_info *find_domain_by_msg(struct sss_domain_info *dom, ++ struct ldb_message *msg); ++ + #endif /* __SYS_DB_H__ */ +diff --git a/src/responder/nss/nss_protocol_grent.c b/src/responder/nss/nss_protocol_grent.c +index 4c7ea9aed..e4494826a 100644 +--- a/src/responder/nss/nss_protocol_grent.c ++++ b/src/responder/nss/nss_protocol_grent.c +@@ -343,6 +343,7 @@ nss_protocol_fill_initgr(struct nss_ctx *nss_ctx, + struct cache_req_result *result) + { + struct sss_domain_info *domain; ++ struct sss_domain_info *grp_dom; + struct ldb_message *user; + struct ldb_message *msg; + struct ldb_message *primary_group_msg; +@@ -400,10 +401,11 @@ nss_protocol_fill_initgr(struct nss_ctx *nss_ctx, + num_results = 0; + for (i = 1; i < result->count; i++) { + msg = result->msgs[i]; +- gid = sss_view_ldb_msg_find_attr_as_uint64(domain, msg, SYSDB_GIDNUM, ++ grp_dom = find_domain_by_msg(domain, msg); ++ gid = sss_view_ldb_msg_find_attr_as_uint64(grp_dom, msg, SYSDB_GIDNUM, + 0); + posix = ldb_msg_find_attr_as_string(msg, SYSDB_POSIX, NULL); +- grp_name = sss_view_ldb_msg_find_attr_as_string(domain, msg, SYSDB_NAME, ++ grp_name = sss_view_ldb_msg_find_attr_as_string(grp_dom, msg, SYSDB_NAME, + NULL); + + if (gid == 0) { +@@ -417,7 +419,7 @@ nss_protocol_fill_initgr(struct nss_ctx *nss_ctx, + } + } + +- if (is_group_filtered(nss_ctx->rctx->ncache, domain, grp_name, gid)) { ++ if (is_group_filtered(nss_ctx->rctx->ncache, grp_dom, grp_name, gid)) { + continue; + } + +-- +2.26.3 + diff --git a/SOURCES/0068-ldap-retry-ldap_install_tls-when-watchdog-interrupti.patch b/SOURCES/0068-ldap-retry-ldap_install_tls-when-watchdog-interrupti.patch new file mode 100644 index 0000000..9f16683 --- /dev/null +++ b/SOURCES/0068-ldap-retry-ldap_install_tls-when-watchdog-interrupti.patch @@ -0,0 +1,180 @@ +From ee16c609497f29731c5a590821d27d0db0ffc91f Mon Sep 17 00:00:00 2001 +From: Iker Pedrosa +Date: Wed, 3 Mar 2021 15:34:49 +0100 +Subject: [PATCH] ldap: retry ldap_install_tls() when watchdog interruption +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When the call to ldap_install_tls() fails because the watchdog +interrupted it, retry it. The watchdog interruption is detected by +checking the value of the ticks before and after the call to +ldap_install_tls(). + +Resolves: https://github.com/SSSD/sssd/issues/5531 + +Reviewed-by: Pavel Březina +--- + src/providers/ldap/sdap_async_connection.c | 27 +++++++++++++++++++++- + src/util/sss_ldap.c | 12 ++++++++++ + src/util/util.h | 1 + + src/util/util_errors.c | 3 +++ + src/util/util_errors.h | 3 +++ + src/util/util_watchdog.c | 5 ++++ + 6 files changed, 50 insertions(+), 1 deletion(-) + +diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c +index afa31ea0f..db963044e 100644 +--- a/src/providers/ldap/sdap_async_connection.c ++++ b/src/providers/ldap/sdap_async_connection.c +@@ -30,6 +30,8 @@ + #include "providers/ldap/sdap_async_private.h" + #include "providers/ldap/ldap_common.h" + ++#define MAX_RETRY_ATTEMPTS 1 ++ + /* ==Connect-to-LDAP-Server=============================================== */ + + struct sdap_rebind_proc_params { +@@ -1447,6 +1449,8 @@ struct sdap_cli_connect_state { + enum connect_tls force_tls; + bool do_auth; + bool use_tls; ++ ++ int retry_attempts; + }; + + static int sdap_cli_resolve_next(struct tevent_req *req); +@@ -1599,16 +1603,37 @@ static void sdap_cli_connect_done(struct tevent_req *subreq) + talloc_zfree(state->sh); + ret = sdap_connect_recv(subreq, state, &state->sh); + talloc_zfree(subreq); +- if (ret) { ++ if (ret == ERR_TLS_HANDSHAKE_INTERRUPTED && ++ state->retry_attempts < MAX_RETRY_ATTEMPTS) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "TLS handshake was interruped, provider will retry\n"); ++ state->retry_attempts++; ++ subreq = sdap_connect_send(state, state->ev, state->opts, ++ state->service->uri, ++ state->service->sockaddr, ++ state->use_tls); ++ ++ if (!subreq) { ++ tevent_req_error(req, ENOMEM); ++ return; ++ } ++ ++ tevent_req_set_callback(subreq, sdap_cli_connect_done, req); ++ return; ++ } else if (ret != EOK) { ++ state->retry_attempts = 0; + /* retry another server */ + be_fo_set_port_status(state->be, state->service->name, + state->srv, PORT_NOT_WORKING); ++ + ret = sdap_cli_resolve_next(req); + if (ret != EOK) { + tevent_req_error(req, ret); + } ++ + return; + } ++ state->retry_attempts = 0; + + if (state->use_rootdse) { + /* fetch the rootDSE this time */ +diff --git a/src/util/sss_ldap.c b/src/util/sss_ldap.c +index 9d1e95217..652b08ea7 100644 +--- a/src/util/sss_ldap.c ++++ b/src/util/sss_ldap.c +@@ -234,6 +234,8 @@ static void sss_ldap_init_sys_connect_done(struct tevent_req *subreq) + int ret; + int lret; + int optret; ++ int ticks_before_install; ++ int ticks_after_install; + + ret = sssd_async_socket_init_recv(subreq, &state->sd); + talloc_zfree(subreq); +@@ -261,7 +263,9 @@ static void sss_ldap_init_sys_connect_done(struct tevent_req *subreq) + } + + if (ldap_is_ldaps_url(state->uri)) { ++ ticks_before_install = get_watchdog_ticks(); + lret = ldap_install_tls(state->ldap); ++ ticks_after_install = get_watchdog_ticks(); + if (lret != LDAP_SUCCESS) { + if (lret == LDAP_LOCAL_ERROR) { + DEBUG(SSSDBG_FUNC_DATA, "TLS/SSL already in place.\n"); +@@ -283,6 +287,14 @@ static void sss_ldap_init_sys_connect_done(struct tevent_req *subreq) + "Check for certificate issues."); + } + ++ if (ticks_after_install > ticks_before_install) { ++ ret = ERR_TLS_HANDSHAKE_INTERRUPTED; ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Assuming %s\n", ++ sss_ldap_err2string(ret)); ++ goto fail; ++ } ++ + ret = EIO; + goto fail; + } +diff --git a/src/util/util.h b/src/util/util.h +index 486394448..94c2e6e3b 100644 +--- a/src/util/util.h ++++ b/src/util/util.h +@@ -737,6 +737,7 @@ int sss_unique_filename(TALLOC_CTX *owner, char *path_tmpl); + /* from util_watchdog.c */ + int setup_watchdog(struct tevent_context *ev, int interval); + void teardown_watchdog(void); ++int get_watchdog_ticks(void); + + /* from files.c */ + int sss_remove_tree(const char *root); +diff --git a/src/util/util_errors.c b/src/util/util_errors.c +index c35a99a54..0eeaa346c 100644 +--- a/src/util/util_errors.c ++++ b/src/util/util_errors.c +@@ -121,6 +121,9 @@ struct err_string error_to_str[] = { + { "The last GetAccountDomain() result is still valid" }, /* ERR_GET_ACCT_DOM_CACHED */ + { "ID is outside the allowed range" }, /* ERR_ID_OUTSIDE_RANGE */ + { "Group ID is duplicated" }, /* ERR_GID_DUPLICATED */ ++ ++ { "TLS handshake was interrupted"}, /* ERR_TLS_HANDSHAKE_INTERRUPTED */ ++ + { "ERR_LAST" } /* ERR_LAST */ + }; + +diff --git a/src/util/util_errors.h b/src/util/util_errors.h +index 470f62f9e..366b75650 100644 +--- a/src/util/util_errors.h ++++ b/src/util/util_errors.h +@@ -143,6 +143,9 @@ enum sssd_errors { + ERR_GET_ACCT_DOM_CACHED, + ERR_ID_OUTSIDE_RANGE, + ERR_GID_DUPLICATED, ++ ++ ERR_TLS_HANDSHAKE_INTERRUPTED, ++ + ERR_LAST /* ALWAYS LAST */ + }; + +diff --git a/src/util/util_watchdog.c b/src/util/util_watchdog.c +index 69160fbdf..7642bfd53 100644 +--- a/src/util/util_watchdog.c ++++ b/src/util/util_watchdog.c +@@ -259,3 +259,8 @@ void teardown_watchdog(void) + /* and kill the watchdog event */ + talloc_free(watchdog_ctx.te); + } ++ ++int get_watchdog_ticks(void) ++{ ++ return __sync_add_and_fetch(&watchdog_ctx.ticks, 0); ++} +-- +2.26.3 + diff --git a/SPECS/sssd.spec b/SPECS/sssd.spec index 18f2e38..a9f72f5 100644 --- a/SPECS/sssd.spec +++ b/SPECS/sssd.spec @@ -50,7 +50,7 @@ Name: sssd Version: 1.16.5 -Release: 10%{?dist}.7 +Release: 10%{?dist}.8 Group: Applications/System Summary: System Security Services Daemon License: GPLv3+ @@ -120,6 +120,13 @@ Patch0058: 0058-nss-check-if-groups-are-filtered-during-initgroups.patch Patch0059: 0059-CACHE-Create-timestamp-if-missing.patch Patch0060: 0060-TESTS-Add-test-for-recreating-cache-timestamp.patch Patch0061: 0061-cert-matching.patch +Patch0062: 0062-UTIL-find_domain_by_object_name_ex-changed-log-level.patch +Patch0063: 0063-sudo-do-not-search-by-low-usn-value-to-improve-perfo.patch +Patch0064: 0064-ldap-fix-modifytimestamp-debugging-leftovers.patch +Patch0065: 0065-sss_domain_info-add-not_found_counter.patch +Patch0066: 0066-AD-read-trusted-domains-from-local-domain-as-well.patch +Patch0067: 0067-negcache-use-right-domain-in-nss_protocol_fill_initg.patch +Patch0068: 0068-ldap-retry-ldap_install_tls-when-watchdog-interrupti.patch #Those patches should not be removed in RHEL-7 Patch0999: 0999-NOUPSTREAM-Default-to-root-if-sssd-user-is-not-spec @@ -1295,6 +1302,13 @@ systemctl try-restart sssd >/dev/null 2>&1 || : } %changelog +* Mon Apr 26 2021 Alexey Tikhonov 1.16.5-10.8 +- Resolves: rhbz#1910131 - sssd throwing error " Unable to parse name test' [1432158283]: The internal name format cannot be parsed" at debug_level 2 [rhel-7.9.z] +- Resolves: rhbz#1922244 - First smart refresh query contains modifyTimestamp even if the modifyTimestamp is 0. [rhel-7.9.z] +- Resolves: rhbz#1935685 - SSSD not detecting subdomain from AD forest (7.9z) +- Resolves: rhbz#1945552 - IPA missing secondary IPA Posix groups in latest sssd 1.16.5-10.el7_9.7 [rhel-7.9.z] +- Resolves: rhbz#1839972 - Authentication handshake (ldap_install_tls()) fails due to underlying openssl operation failing with EINTR [rhel-7.9.z] + * Thu Dec 10 2020 Alexey Tikhonov 1.16.5-10.7 - Resolves: rhbz#1875514 - filter_groups option partially filters the group from 'id' output of the user because gidNumber still appears in 'id' output [rhel-7.9.z] - Resolves: rhbz#1772513 - SSSD is generating lot of LDAP queries in a very large environment [rhel-7.9.z]