From 45d81bea72b5c0655b17432ce15813c10e83768b Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Jan 17 2017 15:26:15 +0000 Subject: import sssd-1.14.0-43.el7_3.11 --- diff --git a/SOURCES/0148-IPA-AD-check-auth-ctx-before-using-it.patch b/SOURCES/0148-IPA-AD-check-auth-ctx-before-using-it.patch new file mode 100644 index 0000000..d6ad243 --- /dev/null +++ b/SOURCES/0148-IPA-AD-check-auth-ctx-before-using-it.patch @@ -0,0 +1,92 @@ +From 1083c5f195ecf29435f24e136cf6470992614494 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Tue, 8 Nov 2016 11:51:57 +0100 +Subject: [PATCH 148/149] IPA/AD: check auth ctx before using it + +In e6b6b9fa79c67d7d2698bc7e33d2e2f6bb53d483 a feature was introduced to +set the 'canonicalize' option in the system-wide Kerberos configuration +according to the settings in SSSD if the AD or IPA provider were used. +Unfortunately the patch implied that the auth provider is the same as +the id provider which might not always be the case. A different auth +provider caused a crash in the backend which is fixed by this patch. + +Resolves https://fedorahosted.org/sssd/ticket/3234 + +Reviewed-by: Petr Cech +(cherry picked from commit ea11ed3ea6291488dd762033246edc4ce3951aeb) +--- + src/providers/ad/ad_subdomains.c | 13 +++++++++++-- + src/providers/ipa/ipa_subdomains.c | 20 +++++++++++++++++--- + 2 files changed, 28 insertions(+), 5 deletions(-) + +diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c +index 52bf5361fa8de02c7165cbc3513a923ec018fc15..5e57d218c072a2627f165ae072cb761e1a146048 100644 +--- a/src/providers/ad/ad_subdomains.c ++++ b/src/providers/ad/ad_subdomains.c +@@ -618,14 +618,23 @@ static errno_t ad_subdom_reinit(struct ad_subdomains_ctx *subdoms_ctx) + { + const char *path; + errno_t ret; +- bool canonicalize; ++ bool canonicalize = false; + + path = dp_opt_get_string(subdoms_ctx->ad_id_ctx->ad_options->basic, + AD_KRB5_CONFD_PATH); + +- canonicalize = dp_opt_get_bool( ++ if (subdoms_ctx->ad_id_ctx->ad_options->auth_ctx != NULL ++ && subdoms_ctx->ad_id_ctx->ad_options->auth_ctx->opts != NULL) { ++ canonicalize = dp_opt_get_bool( + subdoms_ctx->ad_id_ctx->ad_options->auth_ctx->opts, + KRB5_CANONICALIZE); ++ } else { ++ DEBUG(SSSDBG_CONF_SETTINGS, "Auth provider data is not available, " ++ "most probably because the auth provider " ++ "is not 'ad'. Kerberos configuration " ++ "snippet to set the 'canonicalize' option " ++ "will not be created.\n"); ++ } + + ret = sss_write_krb5_conf_snippet(path, canonicalize); + if (ret != EOK) { +diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c +index d02d2d5c05904c54c5e1997aece82f940b7334ee..eb1bc92691da9e82e07595ed84eea35fff78d1a5 100644 +--- a/src/providers/ipa/ipa_subdomains.c ++++ b/src/providers/ipa/ipa_subdomains.c +@@ -73,16 +73,30 @@ static errno_t + ipa_subdom_reinit(struct ipa_subdomains_ctx *ctx) + { + errno_t ret; ++ bool canonicalize = false; + + DEBUG(SSSDBG_TRACE_INTERNAL, + "Re-initializing domain %s\n", ctx->be_ctx->domain->name); + ++ if (ctx->ipa_id_ctx->ipa_options->auth_ctx != NULL ++ && ctx->ipa_id_ctx->ipa_options->auth_ctx->krb5_auth_ctx != NULL ++ && ctx->ipa_id_ctx->ipa_options->auth_ctx->krb5_auth_ctx->opts != NULL ++ ) { ++ canonicalize = dp_opt_get_bool( ++ ctx->ipa_id_ctx->ipa_options->auth_ctx->krb5_auth_ctx->opts, ++ KRB5_CANONICALIZE); ++ } else { ++ DEBUG(SSSDBG_CONF_SETTINGS, "Auth provider data is not available, " ++ "most probably because the auth provider " ++ "is not 'ipa'. Kerberos configuration " ++ "snippet to set the 'canonicalize' option " ++ "will not be created.\n"); ++ } ++ + ret = sss_write_krb5_conf_snippet( + dp_opt_get_string(ctx->ipa_id_ctx->ipa_options->basic, + IPA_KRB5_CONFD_PATH), +- dp_opt_get_bool( +- ctx->ipa_id_ctx->ipa_options->auth_ctx->krb5_auth_ctx->opts, +- KRB5_CANONICALIZE)); ++ canonicalize); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, "sss_write_krb5_conf_snippet failed.\n"); + /* Just continue */ +-- +2.7.4 + diff --git a/SOURCES/0149-Qualify-ghost-user-attribute-in-case-ldap_group_nest.patch b/SOURCES/0149-Qualify-ghost-user-attribute-in-case-ldap_group_nest.patch new file mode 100644 index 0000000..9809cf2 --- /dev/null +++ b/SOURCES/0149-Qualify-ghost-user-attribute-in-case-ldap_group_nest.patch @@ -0,0 +1,60 @@ +From 362911a85e3aa244cdbdf75b8b4131bb26396d19 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Wed, 9 Nov 2016 11:59:10 +0100 +Subject: [PATCH 149/149] Qualify ghost user attribute in case + ldap_group_nesting_level is set to 0 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When the sssd is set to not resolve nested groups with RFC2307bis, then +the LDAP provider takes a different path. We didn't qualify the ghost +users in this case. + +Resolves: +https://fedorahosted.org/sssd/ticket/3236 + +Reviewed-by: Lukáš Slebodník +(cherry picked from commit 538a7f1dd8339b90e0cfc64e7919a34d1d5c10d3) +--- + src/providers/ldap/sdap_async_groups.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c +index 72760b75acae4cb6ce15c72f16dae8e859d89847..49a1934b2604e6a6af8ee8e8b3d1f88d2029658d 100644 +--- a/src/providers/ldap/sdap_async_groups.c ++++ b/src/providers/ldap/sdap_async_groups.c +@@ -1659,7 +1659,7 @@ static void sdap_process_group_members(struct tevent_req *subreq) + struct sdap_process_group_state *state = + tevent_req_data(req, struct sdap_process_group_state); + struct ldb_message_element *el; +- uint8_t* name_string; ++ char *name_string; + + state->check_count--; + DEBUG(SSSDBG_TRACE_ALL, "Members remaining: %zu\n", state->check_count); +@@ -1685,11 +1685,18 @@ static void sdap_process_group_members(struct tevent_req *subreq) + goto next; + } + +- name_string = el[0].values[0].data; ++ name_string = sss_create_internal_fqname(state, ++ (const char *) el[0].values[0].data, ++ state->dom->name); ++ if (name_string == NULL) { ++ ret = ENOMEM; ++ goto next; ++ } ++ + state->ghost_dns->values[state->ghost_dns->num_values].data = +- talloc_steal(state->ghost_dns->values, name_string); ++ talloc_steal(state->ghost_dns->values, (uint8_t *) name_string); + state->ghost_dns->values[state->ghost_dns->num_values].length = +- strlen((char *)name_string); ++ strlen(name_string); + state->ghost_dns->num_values++; + + next: +-- +2.7.4 + diff --git a/SOURCES/0150-SYSDB-Split-sysdb_try_to_find_expected_dn-into-small.patch b/SOURCES/0150-SYSDB-Split-sysdb_try_to_find_expected_dn-into-small.patch new file mode 100644 index 0000000..ee1e343 --- /dev/null +++ b/SOURCES/0150-SYSDB-Split-sysdb_try_to_find_expected_dn-into-small.patch @@ -0,0 +1,342 @@ +From 57a070724f42bb01b8bb3f866e906f40643e0421 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Fri, 28 Oct 2016 13:46:02 +0200 +Subject: [PATCH 150/151] SYSDB: Split sysdb_try_to_find_expected_dn() into + smaller functions + +The function sysdb_try_to_find_expected_dn was performing several matching +algorithms and thus it was getting big and hard to extend. This patch +doesn't contain any functional changes, only shuffles the code around +and splits the monolithic sysdb_try_to_find_expected_dn function into +smaller blocks. + +Reviewed-by: Sumit Bose +(cherry picked from commit e5a984093ad7921c83da75272cede2b0e52ba2d6) +--- + src/db/sysdb_subdomains.c | 278 +++++++++++++++++++++++++++++----------------- + 1 file changed, 179 insertions(+), 99 deletions(-) + +diff --git a/src/db/sysdb_subdomains.c b/src/db/sysdb_subdomains.c +index ff83f914f31d566e050c74a3ef5f5745f8c93add..b011bad6c988db952622e7ddaabf015ec24e54ba 100644 +--- a/src/db/sysdb_subdomains.c ++++ b/src/db/sysdb_subdomains.c +@@ -1145,74 +1145,29 @@ done: + return ret; + } + +-errno_t sysdb_try_to_find_expected_dn(struct sss_domain_info *dom, +- const char *domain_component_name, +- struct sysdb_attrs **usr_attrs, +- size_t count, +- struct sysdb_attrs **exp_usr) ++static errno_t match_cn_users(TALLOC_CTX *tmp_ctx, ++ struct sysdb_attrs **usr_attrs, ++ size_t count, ++ const char *dom_basedn, ++ struct sysdb_attrs **_result) + { +- char *dom_basedn; +- size_t dom_basedn_len; +- char *expected_basedn; +- size_t expected_basedn_len; ++ errno_t ret; ++ const char *orig_dn; + size_t dn_len; +- const char *orig_dn; +- size_t c = 0; +- int ret; +- TALLOC_CTX *tmp_ctx; +- struct ldb_context *ldb_ctx; +- struct ldb_dn *ldb_dom_basedn; +- int dom_basedn_comp_num; +- struct ldb_dn *ldb_dn; +- int dn_comp_num; +- const char *component_name; + struct sysdb_attrs *result = NULL; + const char *result_dn_str = NULL; ++ char *cn_users_basedn; ++ size_t cn_users_basedn_len; + +- if (dom == NULL || domain_component_name == NULL || usr_attrs == NULL +- || count == 0) { +- return EINVAL; +- } +- +- tmp_ctx = talloc_new(NULL); +- if (tmp_ctx == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n"); +- return ENOMEM; +- } +- +- ret = domain_to_basedn(tmp_ctx, dom->name, &dom_basedn); +- if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, "domain_to_basedn failed.\n"); +- goto done; +- } +- expected_basedn = talloc_asprintf(tmp_ctx, "%s%s", "cn=users,", dom_basedn); +- if (expected_basedn == NULL) { ++ cn_users_basedn = talloc_asprintf(tmp_ctx, "%s%s", "cn=users,", dom_basedn); ++ if (cn_users_basedn == NULL) { + ret = ENOMEM; + goto done; + } ++ cn_users_basedn_len = strlen(cn_users_basedn); ++ DEBUG(SSSDBG_TRACE_ALL, "cn=users baseDN is [%s].\n", cn_users_basedn); + +- ldb_ctx = sysdb_ctx_get_ldb(dom->sysdb); +- if (ldb_ctx == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, "Missing ldb context.\n"); +- ret = EINVAL; +- goto done; +- } +- +- ldb_dom_basedn = ldb_dn_new(tmp_ctx, ldb_ctx, dom_basedn); +- if (ldb_dom_basedn == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed.\n"); +- ret = ENOMEM; +- goto done; +- } +- +- dom_basedn_comp_num = ldb_dn_get_comp_num(ldb_dom_basedn); +- dom_basedn_comp_num++; +- +- DEBUG(SSSDBG_TRACE_ALL, "Expected BaseDN is [%s].\n", expected_basedn); +- expected_basedn_len = strlen(expected_basedn); +- dom_basedn_len = strlen(dom_basedn); +- +- for (c = 0; c < count; c++) { ++ for (size_t c = 0; c < count; c++) { + ret = sysdb_attrs_get_string(usr_attrs[c], SYSDB_ORIG_DN, &orig_dn); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n"); +@@ -1220,9 +1175,9 @@ errno_t sysdb_try_to_find_expected_dn(struct sss_domain_info *dom, + } + dn_len = strlen(orig_dn); + +- if (dn_len > expected_basedn_len +- && strcasecmp(orig_dn + (dn_len - expected_basedn_len), +- expected_basedn) == 0) { ++ if (dn_len > cn_users_basedn_len ++ && strcasecmp(orig_dn + (dn_len - cn_users_basedn_len), ++ cn_users_basedn) == 0) { + DEBUG(SSSDBG_TRACE_ALL, + "Found matching dn [%s].\n", orig_dn); + if (result != NULL) { +@@ -1237,52 +1192,177 @@ errno_t sysdb_try_to_find_expected_dn(struct sss_domain_info *dom, + } + } + +- if (result == NULL) { +- for (c = 0; c < count; c++) { +- ret = sysdb_attrs_get_string(usr_attrs[c], SYSDB_ORIG_DN, &orig_dn); +- if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n"); ++ ret = EOK; ++done: ++ *_result = result; ++ return ret; ++} ++ ++static errno_t match_non_dc_comp(TALLOC_CTX *tmp_ctx, ++ struct sss_domain_info *dom, ++ struct sysdb_attrs **usr_attrs, ++ size_t count, ++ struct ldb_dn *ldb_basedn, ++ const char *basedn, ++ const char *domain_component_name, ++ struct sysdb_attrs **_result) ++{ ++ errno_t ret; ++ const char *orig_dn; ++ size_t orig_dn_len; ++ size_t basedn_len; ++ struct ldb_context *ldb_ctx; ++ struct ldb_dn *ldb_orig_dn; ++ int dn_comp_num; ++ int basedn_comp_num; ++ const char *component_name; ++ struct sysdb_attrs *result = NULL; ++ const char *result_dn_str = NULL; ++ ++ ldb_ctx = sysdb_ctx_get_ldb(dom->sysdb); ++ if (ldb_ctx == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "Missing ldb context.\n"); ++ ret = EINVAL; ++ goto done; ++ } ++ ++ basedn_len = strlen(basedn); ++ ++ basedn_comp_num = ldb_dn_get_comp_num(ldb_basedn); ++ basedn_comp_num++; ++ ++ for (size_t c = 0; c < count; c++) { ++ ret = sysdb_attrs_get_string(usr_attrs[c], SYSDB_ORIG_DN, &orig_dn); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_string failed.\n"); ++ goto done; ++ } ++ orig_dn_len = strlen(orig_dn); ++ ++ if (orig_dn_len > basedn_len ++ /* Does the user's original DN with the non-domain part ++ * stripped match the domain base DN? ++ */ ++ && strcasecmp(orig_dn + (orig_dn_len - basedn_len), ++ basedn) == 0) { ++ ldb_orig_dn = ldb_dn_new(tmp_ctx, ldb_ctx, orig_dn); ++ if (ldb_orig_dn == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed"); ++ ret = ENOMEM; + goto done; + } +- dn_len = strlen(orig_dn); + +- if (dn_len > dom_basedn_len +- && strcasecmp(orig_dn + (dn_len - dom_basedn_len), +- dom_basedn) == 0) { +- ldb_dn = ldb_dn_new(tmp_ctx, ldb_ctx, orig_dn); +- if (ldb_dn == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed"); +- ret = ENOMEM; +- goto done; +- } +- +- dn_comp_num = ldb_dn_get_comp_num(ldb_dn); +- if (dn_comp_num > dom_basedn_comp_num) { +- component_name = ldb_dn_get_component_name(ldb_dn, +- (dn_comp_num - dom_basedn_comp_num)); +- DEBUG(SSSDBG_TRACE_ALL, "Comparing [%s] and [%s].\n", +- component_name, +- domain_component_name); +- if (component_name != NULL +- && strcasecmp(component_name, +- domain_component_name) != 0) { +- DEBUG(SSSDBG_TRACE_ALL, +- "Found matching dn [%s].\n", orig_dn); +- if (result != NULL) { +- DEBUG(SSSDBG_OP_FAILURE, +- "Found 2 matching DN [%s] and [%s], " +- "expecting only 1.\n", result_dn_str, orig_dn); +- ret = EINVAL; +- goto done; +- } +- result = usr_attrs[c]; +- result_dn_str = orig_dn; ++ dn_comp_num = ldb_dn_get_comp_num(ldb_orig_dn); ++ if (dn_comp_num > basedn_comp_num) { ++ component_name = ldb_dn_get_component_name(ldb_orig_dn, ++ (dn_comp_num - basedn_comp_num)); ++ DEBUG(SSSDBG_TRACE_ALL, "Comparing [%s] and [%s].\n", ++ component_name, ++ domain_component_name); ++ /* If the component is NOT a DC component, then the entry ++ * must come from our domain, perhaps from a child container. ++ * If it matched the DC component, the entry was from a child ++ * subdomain different from this one. ++ */ ++ if (component_name != NULL ++ && strcasecmp(component_name, ++ domain_component_name) != 0) { ++ DEBUG(SSSDBG_TRACE_ALL, ++ "Found matching dn [%s].\n", orig_dn); ++ if (result != NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "Found 2 matching DN [%s] and [%s], " ++ "expecting only 1.\n", result_dn_str, orig_dn); ++ ret = EINVAL; ++ goto done; + } ++ result = usr_attrs[c]; ++ result_dn_str = orig_dn; + } + } + } + } + ++ ret = EOK; ++ *_result = result; ++done: ++ return ret; ++} ++ ++static errno_t match_basedn(TALLOC_CTX *tmp_ctx, ++ struct sss_domain_info *dom, ++ struct sysdb_attrs **usr_attrs, ++ size_t count, ++ const char *dom_basedn, ++ const char *domain_component_name, ++ struct sysdb_attrs **_result) ++{ ++ struct ldb_context *ldb_ctx; ++ struct ldb_dn *ldb_dom_basedn; ++ ++ ldb_ctx = sysdb_ctx_get_ldb(dom->sysdb); ++ if (ldb_ctx == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "Missing ldb context.\n"); ++ return EINVAL; ++ } ++ ++ ++ ldb_dom_basedn = ldb_dn_new(tmp_ctx, ldb_ctx, dom_basedn); ++ if (ldb_dom_basedn == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed.\n"); ++ return ENOMEM; ++ } ++ ++ return match_non_dc_comp(tmp_ctx, dom, ++ usr_attrs, count, ++ ldb_dom_basedn, dom_basedn, ++ domain_component_name, ++ _result); ++} ++ ++errno_t sysdb_try_to_find_expected_dn(struct sss_domain_info *dom, ++ const char *domain_component_name, ++ struct sysdb_attrs **usr_attrs, ++ size_t count, ++ struct sysdb_attrs **exp_usr) ++{ ++ char *dom_basedn; ++ int ret; ++ TALLOC_CTX *tmp_ctx; ++ struct sysdb_attrs *result = NULL; ++ ++ if (dom == NULL || domain_component_name == NULL ++ || usr_attrs == NULL || count == 0) { ++ return EINVAL; ++ } ++ ++ tmp_ctx = talloc_new(NULL); ++ if (tmp_ctx == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n"); ++ return ENOMEM; ++ } ++ ++ ret = domain_to_basedn(tmp_ctx, dom->name, &dom_basedn); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, "domain_to_basedn failed.\n"); ++ ret = EINVAL; ++ goto done; ++ } ++ ++ ret = match_cn_users(tmp_ctx, usr_attrs, count, dom_basedn, &result); ++ if (ret != EOK) { ++ goto done; ++ } ++ ++ if (result == NULL) { ++ ret = match_basedn(tmp_ctx, dom, usr_attrs, ++ count, dom_basedn, domain_component_name, ++ &result); ++ if (ret != EOK) { ++ goto done; ++ } ++ } ++ + if (result == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "No matching DN found.\n"); + ret = ENOENT; +-- +2.7.4 + diff --git a/SOURCES/0151-SYSDB-Augment-sysdb_try_to_find_expected_dn-to-match.patch b/SOURCES/0151-SYSDB-Augment-sysdb_try_to_find_expected_dn-to-match.patch new file mode 100644 index 0000000..d4e0758 --- /dev/null +++ b/SOURCES/0151-SYSDB-Augment-sysdb_try_to_find_expected_dn-to-match.patch @@ -0,0 +1,283 @@ +From a315e923a930e743de51c05183de383245f1c83e Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Mon, 31 Oct 2016 21:39:57 +0100 +Subject: [PATCH 151/151] SYSDB: Augment sysdb_try_to_find_expected_dn to match + search base as well + +In cases where the domain name in sssd.conf does not match the AD +domain, our previous matching process wouldn't match. This patch +augments the matching as follows: + - the search base is known to sysdb_try_to_find_expected_dn and is + expected to be non-NULL + - the existing matching is ran first + - during the search base, matching, all the non-DC components are + stripped from the search base to 'canonicalize' the search base + - if only a single entry that matches with a non-DC DN component + (matching with a DC component would mean the DN comes from a + different domain) then this entry is a match and is returned + +Resolves: +https://fedorahosted.org/sssd/ticket/3199 + +Reviewed-by: Sumit Bose +(cherry picked from commit 24d8c85fae253f988165c112af208198cf48eef6) +--- + src/db/sysdb.h | 1 + + src/db/sysdb_subdomains.c | 99 ++++++++++++++++++++++++++++++ + src/providers/ldap/sdap_async_initgroups.c | 8 ++- + src/tests/cmocka/test_sysdb_subdomains.c | 43 +++++++++++-- + 4 files changed, 144 insertions(+), 7 deletions(-) + +diff --git a/src/db/sysdb.h b/src/db/sysdb.h +index a0279fb249e1258c9cb73a4fcab55e4b242c61f3..6a1bbf089206970892590e85ae1f5c741a79f969 100644 +--- a/src/db/sysdb.h ++++ b/src/db/sysdb.h +@@ -1296,6 +1296,7 @@ errno_t sysdb_handle_original_uuid(const char *orig_name, + + errno_t sysdb_try_to_find_expected_dn(struct sss_domain_info *dom, + const char *domain_component_name, ++ const char *ldap_search_base, + struct sysdb_attrs **usr_attrs, + size_t count, + struct sysdb_attrs **exp_usr); +diff --git a/src/db/sysdb_subdomains.c b/src/db/sysdb_subdomains.c +index b011bad6c988db952622e7ddaabf015ec24e54ba..780140484f6f023bc6e8c12266e3b81ff016ec10 100644 +--- a/src/db/sysdb_subdomains.c ++++ b/src/db/sysdb_subdomains.c +@@ -1320,8 +1320,97 @@ static errno_t match_basedn(TALLOC_CTX *tmp_ctx, + _result); + } + ++static errno_t match_search_base(TALLOC_CTX *tmp_ctx, ++ struct sss_domain_info *dom, ++ const char *domain_component_name, ++ const char *domain_search_base, ++ struct sysdb_attrs **usr_attrs, ++ size_t count, ++ struct sysdb_attrs **_result) ++{ ++ errno_t ret; ++ bool ok; ++ const char *search_base; ++ struct ldb_context *ldb_ctx; ++ struct sysdb_attrs *result = NULL; ++ struct ldb_dn *ldb_search_base; ++ int search_base_comp_num; ++ int non_dc_comp_num; ++ const char *component_name; ++ ++ ldb_ctx = sysdb_ctx_get_ldb(dom->sysdb); ++ if (ldb_ctx == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "Missing ldb context.\n"); ++ ret = EINVAL; ++ goto done; ++ } ++ ++ ldb_search_base = ldb_dn_new(tmp_ctx, ldb_ctx, domain_search_base); ++ if (ldb_search_base == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "ldb_dn_new failed.\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ /* strip non-DC components from the search base */ ++ search_base_comp_num = ldb_dn_get_comp_num(ldb_search_base); ++ for (non_dc_comp_num = 0; ++ non_dc_comp_num < search_base_comp_num; ++ non_dc_comp_num++) { ++ ++ component_name = ldb_dn_get_component_name(ldb_search_base, ++ non_dc_comp_num); ++ if (strcasecmp(domain_component_name, component_name) == 0) { ++ break; ++ } ++ } ++ ++ if (non_dc_comp_num == search_base_comp_num) { ++ /* The search base does not have any non-DC components, the search wouldn't ++ * match anyway ++ */ ++ ret = EOK; ++ *_result = NULL; ++ goto done; ++ } ++ ++ ok = ldb_dn_remove_child_components(ldb_search_base, non_dc_comp_num); ++ if (!ok) { ++ ret = EINVAL; ++ goto done; ++ } ++ ++ search_base = ldb_dn_get_linearized(ldb_search_base); ++ if (search_base == NULL) { ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ ret = match_cn_users(tmp_ctx, usr_attrs, count, search_base, &result); ++ if (ret != EOK) { ++ goto done; ++ } ++ ++ if (result == NULL) { ++ ret = match_non_dc_comp(tmp_ctx, dom, ++ usr_attrs, count, ++ ldb_search_base, search_base, ++ domain_component_name, ++ &result); ++ if (ret != EOK) { ++ goto done; ++ } ++ } ++ ++ ret = EOK; ++ *_result = result; ++done: ++ return ret; ++} ++ + errno_t sysdb_try_to_find_expected_dn(struct sss_domain_info *dom, + const char *domain_component_name, ++ const char *domain_search_base, + struct sysdb_attrs **usr_attrs, + size_t count, + struct sysdb_attrs **exp_usr) +@@ -1332,6 +1421,7 @@ errno_t sysdb_try_to_find_expected_dn(struct sss_domain_info *dom, + struct sysdb_attrs *result = NULL; + + if (dom == NULL || domain_component_name == NULL ++ || domain_search_base == NULL + || usr_attrs == NULL || count == 0) { + return EINVAL; + } +@@ -1364,6 +1454,15 @@ errno_t sysdb_try_to_find_expected_dn(struct sss_domain_info *dom, + } + + if (result == NULL) { ++ ret = match_search_base(tmp_ctx, dom, domain_component_name, ++ domain_search_base, usr_attrs, count, ++ &result); ++ if (ret != EOK) { ++ goto done; ++ } ++ } ++ ++ if (result == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "No matching DN found.\n"); + ret = ENOENT; + goto done; +diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c +index 8eaba261c49082d086df9f19464ac0f40fae71fb..1173f4a875a1ea79990ff491ee7f2512f8435ac7 100644 +--- a/src/providers/ldap/sdap_async_initgroups.c ++++ b/src/providers/ldap/sdap_async_initgroups.c +@@ -2947,7 +2947,13 @@ static void sdap_get_initgr_user(struct tevent_req *subreq) + DEBUG(SSSDBG_OP_FAILURE, + "Expected one user entry and got %zu\n", count); + +- ret = sysdb_try_to_find_expected_dn(state->dom, "dc", usr_attrs, count, ++ /* When matching against a search base, it's sufficient to pick only ++ * the first search base because all bases in a single domain would ++ * have the same DC= components ++ */ ++ ret = sysdb_try_to_find_expected_dn(state->dom, "dc", ++ state->sdom->search_bases[0]->basedn, ++ usr_attrs, count, + &state->orig_user); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, +diff --git a/src/tests/cmocka/test_sysdb_subdomains.c b/src/tests/cmocka/test_sysdb_subdomains.c +index c9db56841e841472c81d00a79f475dbbd975ccb0..52056e0435d2793893f1a4e336f38acf7a70b2c0 100644 +--- a/src/tests/cmocka/test_sysdb_subdomains.c ++++ b/src/tests/cmocka/test_sysdb_subdomains.c +@@ -520,7 +520,9 @@ static void test_try_to_find_expected_dn(void **state) + int ret; + struct sysdb_attrs *result; + struct sysdb_attrs *usr_attrs[10] = { NULL }; ++ struct sysdb_attrs *dom_usr_attrs[10] = { NULL }; + struct sss_domain_info *dom; ++ char *dom_basedn; + struct subdom_test_ctx *test_ctx = + talloc_get_type(*state, struct subdom_test_ctx); + +@@ -528,6 +530,9 @@ static void test_try_to_find_expected_dn(void **state) + "child2.test_sysdb_subdomains_2", true); + assert_non_null(dom); + ++ ret = domain_to_basedn(test_ctx, dom->name, &dom_basedn); ++ assert_int_equal(ret, EOK); ++ + usr_attrs[0] = sysdb_new_attrs(test_ctx); + assert_non_null(usr_attrs[0]); + +@@ -535,13 +540,13 @@ static void test_try_to_find_expected_dn(void **state) + "uid=user,cn=abc,dc=c2,dc=child2,dc=test_sysdb_subdomains_2"); + assert_int_equal(ret, EOK); + +- ret = sysdb_try_to_find_expected_dn(NULL, NULL, NULL, 0, NULL); ++ ret = sysdb_try_to_find_expected_dn(NULL, NULL, NULL, NULL, 0, NULL); + assert_int_equal(ret, EINVAL); + +- ret = sysdb_try_to_find_expected_dn(dom, "dc", usr_attrs, 1, &result); ++ ret = sysdb_try_to_find_expected_dn(dom, "dc", dom_basedn, usr_attrs, 1, &result); + assert_int_equal(ret, ENOENT); + +- ret = sysdb_try_to_find_expected_dn(dom, "xy", usr_attrs, 1, &result); ++ ret = sysdb_try_to_find_expected_dn(dom, "xy", dom_basedn, usr_attrs, 1, &result); + assert_int_equal(ret, EOK); + assert_ptr_equal(result, usr_attrs[0]); + +@@ -559,11 +564,11 @@ static void test_try_to_find_expected_dn(void **state) + "uid=user2,cn=abc,dc=c2,dc=child2,dc=test_sysdb_subdomains_2"); + assert_int_equal(ret, EOK); + +- ret = sysdb_try_to_find_expected_dn(dom, "dc", usr_attrs, 3, &result); ++ ret = sysdb_try_to_find_expected_dn(dom, "dc", dom_basedn, usr_attrs, 3, &result); + assert_int_equal(ret, EOK); + assert_ptr_equal(result, usr_attrs[1]); + +- ret = sysdb_try_to_find_expected_dn(dom, "xy", usr_attrs, 3, &result); ++ ret = sysdb_try_to_find_expected_dn(dom, "xy", dom_basedn, usr_attrs, 3, &result); + assert_int_equal(ret, EINVAL); + + /* Make sure cn=users match is preferred */ +@@ -575,10 +580,36 @@ static void test_try_to_find_expected_dn(void **state) + "uid=user2,cn=abc,cn=users,dc=child2,dc=test_sysdb_subdomains_2"); + assert_int_equal(ret, EOK); + +- ret = sysdb_try_to_find_expected_dn(dom, "dc", usr_attrs, 3, &result); ++ ret = sysdb_try_to_find_expected_dn(dom, "dc", dom_basedn, usr_attrs, 3, &result); + assert_int_equal(ret, EOK); + assert_ptr_equal(result, usr_attrs[2]); + ++ /* test a case where the domain name does not match the basedn */ ++ dom->name = discard_const("default"); ++ dom_usr_attrs[0] = usr_attrs[0]; ++ ++ ret = sysdb_try_to_find_expected_dn(dom, "dc", dom_basedn, dom_usr_attrs, 1, &result); ++ assert_int_equal(ret, ENOENT); ++ ++ dom_usr_attrs[1] = usr_attrs[1]; ++ dom_usr_attrs[2] = usr_attrs[2]; ++ ++ /* Make sure cn=users match is preferred */ ++ ret = sysdb_try_to_find_expected_dn(dom, "dc", dom_basedn, dom_usr_attrs, 3, &result); ++ assert_int_equal(ret, EOK); ++ assert_ptr_equal(result, dom_usr_attrs[2]); ++ ++ talloc_free(usr_attrs[2]); ++ usr_attrs[2] = sysdb_new_attrs(test_ctx); ++ assert_non_null(usr_attrs[2]); ++ ret = sysdb_attrs_add_string(usr_attrs[2], SYSDB_ORIG_DN, ++ "uid=user2,cn=abc,dc=c2,dc=child2,dc=test_sysdb_subdomains_2"); ++ assert_int_equal(ret, EOK); ++ ++ dom_usr_attrs[2] = usr_attrs[2]; ++ ret = sysdb_try_to_find_expected_dn(dom, "dc", dom_basedn, dom_usr_attrs, 3, &result); ++ assert_int_equal(ret, EOK); ++ assert_ptr_equal(result, usr_attrs[1]); + + talloc_free(usr_attrs[0]); + talloc_free(usr_attrs[1]); +-- +2.7.4 + diff --git a/SOURCES/0152-SYSDB-Adding-lowercase-sudoUser-form.patch b/SOURCES/0152-SYSDB-Adding-lowercase-sudoUser-form.patch new file mode 100644 index 0000000..504689e --- /dev/null +++ b/SOURCES/0152-SYSDB-Adding-lowercase-sudoUser-form.patch @@ -0,0 +1,106 @@ +From 81ae14a34ad568b39b0077cc88112941802df27d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20=C4=8Cech?= +Date: Wed, 12 Oct 2016 16:48:38 +0200 +Subject: [PATCH 152/153] SYSDB: Adding lowercase sudoUser form +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If domain is not case sensitive we add lowercase form of usernames +to sudoUser attributes. So we actually able to apply sudoRule on +user Administrator@... with login admnistrator@... + +Resolves: +https://fedorahosted.org/sssd/ticket/3203 + +Reviewed-by: Pavel Březina +(cherry picked from commit f4a1046bb88d7a0ab3617e49ae94bfa849d10645) +--- + src/db/sysdb_sudo.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 64 insertions(+) + +diff --git a/src/db/sysdb_sudo.c b/src/db/sysdb_sudo.c +index 601fb63f236a7ed9eede130fd8cf4c3a1559fc4b..4bd93ffc60caa1ce48b72ee207899da0c4196d61 100644 +--- a/src/db/sysdb_sudo.c ++++ b/src/db/sysdb_sudo.c +@@ -852,6 +852,65 @@ sysdb_sudo_add_sss_attrs(struct sysdb_attrs *rule, + return EOK; + } + ++static errno_t sysdb_sudo_add_lowered_users(struct sss_domain_info *domain, ++ struct sysdb_attrs *rule) ++{ ++ TALLOC_CTX *tmp_ctx; ++ const char **users = NULL; ++ const char *lowered = NULL; ++ errno_t ret; ++ ++ if (domain->case_sensitive == true || rule == NULL) { ++ return EOK; ++ } ++ ++ tmp_ctx = talloc_new(NULL); ++ if (tmp_ctx == NULL) { ++ return ENOMEM; ++ } ++ ++ ret = sysdb_attrs_get_string_array(rule, SYSDB_SUDO_CACHE_AT_USER, tmp_ctx, ++ &users); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, "Unable to get %s attribute [%d]: %s\n", ++ SYSDB_SUDO_CACHE_AT_USER, ret, strerror(ret)); ++ goto done; ++ } ++ ++ if (users == NULL) { ++ ret = EOK; ++ goto done; ++ } ++ ++ for (int i = 0; users[i] != NULL; i++) { ++ lowered = sss_tc_utf8_str_tolower(tmp_ctx, users[i]); ++ if (lowered == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "Cannot convert name to lowercase.\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ if (strcmp(users[i], lowered) == 0) { ++ /* It protects us from adding duplicate. */ ++ continue; ++ } ++ ++ ret = sysdb_attrs_add_string(rule, SYSDB_SUDO_CACHE_AT_USER, lowered); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "Unable to add %s attribute [%d]: %s\n", ++ SYSDB_SUDO_CACHE_AT_USER, ret, strerror(ret)); ++ goto done; ++ } ++ } ++ ++ ret = EOK; ++ ++done: ++ talloc_zfree(tmp_ctx); ++ return ret; ++} ++ + static errno_t + sysdb_sudo_store_rule(struct sss_domain_info *domain, + struct sysdb_attrs *rule, +@@ -868,6 +927,11 @@ sysdb_sudo_store_rule(struct sss_domain_info *domain, + + DEBUG(SSSDBG_TRACE_FUNC, "Adding sudo rule %s\n", name); + ++ ret = sysdb_sudo_add_lowered_users(domain, rule); ++ if (ret != EOK) { ++ return ret; ++ } ++ + ret = sysdb_sudo_add_sss_attrs(rule, name, cache_timeout, now); + if (ret != EOK) { + return ret; +-- +2.7.4 + diff --git a/SOURCES/0153-SYSDB-Fixing-of-sudorule-without-a-sudoUser.patch b/SOURCES/0153-SYSDB-Fixing-of-sudorule-without-a-sudoUser.patch new file mode 100644 index 0000000..ea2bc3f --- /dev/null +++ b/SOURCES/0153-SYSDB-Fixing-of-sudorule-without-a-sudoUser.patch @@ -0,0 +1,47 @@ +From aed255dd1ae6ec40ca15a53c38a13354dd5c88e8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Petr=20=C4=8Cech?= +Date: Wed, 16 Nov 2016 10:09:18 +0100 +Subject: [PATCH 153/153] SYSDB: Fixing of sudorule without a sudoUser + +This patch solved a regression caused by the recent patches +to lowercase sudoUser -- in case sudoUser is missing completely, +we abort the processing of this rule and all others. + +With this patch, we return ERR_MALFORMED_ENTRY and gracefully +skip the malformed rule instead. + +Resolves: +https://fedorahosted.org/sssd/ticket/3241 + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 7e23edbaa7a6bbd0b461d5792535896b6a77928b) +--- + src/db/sysdb_sudo.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/src/db/sysdb_sudo.c b/src/db/sysdb_sudo.c +index 4bd93ffc60caa1ce48b72ee207899da0c4196d61..f5160f19012028f92723b9012fad85d803aa5137 100644 +--- a/src/db/sysdb_sudo.c ++++ b/src/db/sysdb_sudo.c +@@ -874,6 +874,7 @@ static errno_t sysdb_sudo_add_lowered_users(struct sss_domain_info *domain, + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "Unable to get %s attribute [%d]: %s\n", + SYSDB_SUDO_CACHE_AT_USER, ret, strerror(ret)); ++ ret = ERR_MALFORMED_ENTRY; + goto done; + } + +@@ -977,6 +978,10 @@ sysdb_sudo_store(struct sss_domain_info *domain, + /* Multiple CNs are error on server side, we can just ignore this + * rule and save the others. Loud debug message is in logs. */ + continue; ++ } else if (ret == ERR_MALFORMED_ENTRY) { ++ /* Attribute SYSDB_SUDO_CACHE_AT_USER is missing but we can ++ * continue with next sudoRule. */ ++ continue; + } else if (ret != EOK) { + goto done; + } +-- +2.7.4 + diff --git a/SOURCES/0154-MONITOR-Do-not-set-up-watchdog-for-monitor.patch b/SOURCES/0154-MONITOR-Do-not-set-up-watchdog-for-monitor.patch new file mode 100644 index 0000000..20ec5e1 --- /dev/null +++ b/SOURCES/0154-MONITOR-Do-not-set-up-watchdog-for-monitor.patch @@ -0,0 +1,73 @@ +From c7edf2dabc1cc3fc5298c872babf60a3001dfc2f Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Mon, 7 Nov 2016 11:58:20 +0100 +Subject: [PATCH 154/154] MONITOR: Do not set up watchdog for monitor +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +It makes little sense to set up watchdog for monitor because there is no +entity that would restart the monitor. Therefore we should disable the +watchdog for monitor process. + +Resolves: +https://fedorahosted.org/sssd/ticket/3232 + +Reviewed-by: Lukáš Slebodník +(cherry picked from commit fbe6644aa28d93f492434950680c5618eb567712) +--- + src/monitor/monitor.c | 2 ++ + src/util/server.c | 11 +++++++---- + src/util/util.h | 1 + + 3 files changed, 10 insertions(+), 4 deletions(-) + +diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c +index 89dd0a91d1fbd41dd853cf8745de732b7059d02b..0f01580e01b6a0a9ab507a54183e5813133be5a9 100644 +--- a/src/monitor/monitor.c ++++ b/src/monitor/monitor.c +@@ -2880,6 +2880,8 @@ int main(int argc, const char *argv[]) + + /* we want a pid file check */ + flags |= FLAGS_PID_FILE; ++ /* the monitor should not run a watchdog on itself */ ++ flags |= FLAGS_NO_WATCHDOG; + + /* Open before server_setup() does to have logging + * during configuration checking */ +diff --git a/src/util/server.c b/src/util/server.c +index 953cd3d6171bf2fbcefd9b9138c679100d5153c3..013e572e6284b16534910088f7801219251896d8 100644 +--- a/src/util/server.c ++++ b/src/util/server.c +@@ -666,10 +666,13 @@ int server_setup(const char *name, int flags, + ret, strerror(ret)); + return ret; + } +- ret = setup_watchdog(ctx->event_ctx, watchdog_interval); +- if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Watchdog setup failed.\n"); +- return ret; ++ ++ if ((flags & FLAGS_NO_WATCHDOG) == 0) { ++ ret = setup_watchdog(ctx->event_ctx, watchdog_interval); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Watchdog setup failed.\n"); ++ return ret; ++ } + } + + sss_log(SSS_LOG_INFO, "Starting up"); +diff --git a/src/util/util.h b/src/util/util.h +index 4449315f8b1a79ec915bc340b46188c440a27fa3..0cbd88bd5bdb7741148dcc40aeb5ee2abaa4ff98 100644 +--- a/src/util/util.h ++++ b/src/util/util.h +@@ -84,6 +84,7 @@ + #define FLAGS_INTERACTIVE 0x0002 + #define FLAGS_PID_FILE 0x0004 + #define FLAGS_GEN_CONF 0x0008 ++#define FLAGS_NO_WATCHDOG 0x0010 + + #define PIPE_INIT { -1, -1 } + +-- +2.7.4 + diff --git a/SOURCES/0155-AUTOFS-Fix-offline-resolution-of-autofs-maps.patch b/SOURCES/0155-AUTOFS-Fix-offline-resolution-of-autofs-maps.patch new file mode 100644 index 0000000..b8ccb04 --- /dev/null +++ b/SOURCES/0155-AUTOFS-Fix-offline-resolution-of-autofs-maps.patch @@ -0,0 +1,57 @@ +From 3f911325b21c53d3a932c48bc1bac328ec716268 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Thu, 4 Aug 2016 17:58:32 +0200 +Subject: [PATCH 155/155] AUTOFS: Fix offline resolution of autofs maps +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If talking to the Data Provider failed, we never re-tried looking into +the cache. We should consult the cache on DP failures and return cached +results, if possible. + +Resolves: +https://fedorahosted.org/sssd/ticket/3080 + +Reviewed-by: Pavel Březina +--- + src/responder/autofs/autofssrv_cmd.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/src/responder/autofs/autofssrv_cmd.c b/src/responder/autofs/autofssrv_cmd.c +index 9666ab2d195a581f18eaa7ff9bbc4c8167a71b15..f5aa25a483c3b3352f40e8cc66dfd3a24a60af0d 100644 +--- a/src/responder/autofs/autofssrv_cmd.c ++++ b/src/responder/autofs/autofssrv_cmd.c +@@ -871,17 +871,25 @@ static void lookup_automntmap_cache_updated(uint16_t err_maj, uint32_t err_min, + if (err_maj) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Unable to get information from Data Provider\n" +- "Error: %u, %u, %s\n" +- "Will try to return what we have in cache\n", ++ "Error: %u, %u, %s\n" ++ "Will try to return what we have in cache\n", + (unsigned int)err_maj, (unsigned int)err_min, err_msg); +- /* Loop to the next domain if possible */ ++ ++ /* Try to fall back to cache */ ++ ret = lookup_automntmap_step(lookup_ctx); ++ if (ret == EOK) { ++ /* We have cached results to return */ ++ autofs_setent_notify(lookup_ctx->map, ret); ++ return; ++ } ++ ++ /* Otherwise try the next domain */ + if (dctx->cmd_ctx->check_next + && (dctx->domain = get_next_domain(dctx->domain, 0))) { + dctx->check_provider = NEED_CHECK_PROVIDER(dctx->domain->provider); + } + } + +- /* ok the backend returned, search to see if we have updated results */ + ret = lookup_automntmap_step(lookup_ctx); + if (ret != EOK) { + if (ret == EAGAIN) { +-- +2.7.4 + diff --git a/SOURCES/0156-Prevent-use-after-free-in-fd_input_available.patch b/SOURCES/0156-Prevent-use-after-free-in-fd_input_available.patch new file mode 100644 index 0000000..ef0555c --- /dev/null +++ b/SOURCES/0156-Prevent-use-after-free-in-fd_input_available.patch @@ -0,0 +1,71 @@ +From f8ecb57dcb7ce41b572cb67e6d2554296a54e738 Mon Sep 17 00:00:00 2001 +From: Carl Henrik Lunde +Date: Thu, 1 Dec 2016 00:09:00 +0100 +Subject: [PATCH 156/156] Prevent use after free in fd_input_available + +When both TEVENT_FD_WRITE and TEVENT_FD_READ are set, and an error/EOF +occurs when reading from the socket, we will get a use after free +in the second call ares_process_fd. The first call will free the watch +structure via a callback. + +Prevent this by calling ares_process_fd only once. + +Invalid read of size 4 + at fd_input_available (async_resolv.c:147) + by epoll_event_loop (tevent_epoll.c:728) + by epoll_event_loop_once (tevent_epoll.c:926) + by std_event_loop_once (tevent_standard.c:114) + by _tevent_loop_once (tevent.c:533) + by tevent_common_loop_wait (tevent.c:637) + by std_event_loop_wait (tevent_standard.c:140) + by server_loop (server.c:702) + by main (data_provider_be.c:587) + Address ... is 112 bytes inside a block of size 136 free'd + at free (vg_replace_malloc.c:530) + by _talloc_free_internal (talloc.c:1116) + by _talloc_free (talloc.c:1647) + by ares__close_sockets (ares__close_sockets.c:50) + by handle_error (ares_process.c:679) + by read_tcp_data (ares_process.c:391) + by processfds (ares_process.c:138) + by fd_input_available (async_resolv.c:144) + by epoll_event_loop (tevent_epoll.c:728) + by epoll_event_loop_once (tevent_epoll.c:926) + by std_event_loop_once (tevent_standard.c:114) + by _tevent_loop_once (tevent.c:533) + by tevent_common_loop_wait (tevent.c:637) + by std_event_loop_wait (tevent_standard.c:140) + by server_loop (server.c:702) + +Resolves: +https://fedorahosted.org/sssd/ticket/3250 + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 9676b464dd428557ff5a648e1351a3972440396f) +--- + src/resolv/async_resolv.c | 9 +++------ + 1 file changed, 3 insertions(+), 6 deletions(-) + +diff --git a/src/resolv/async_resolv.c b/src/resolv/async_resolv.c +index 58d5c6e550bb34cbaa50517323133fad4f900980..e29f679423eeccae1c8fb7af5fdafc69f051741a 100644 +--- a/src/resolv/async_resolv.c ++++ b/src/resolv/async_resolv.c +@@ -140,12 +140,9 @@ fd_input_available(struct tevent_context *ev, struct tevent_fd *fde, + return; + } + +- if (flags & TEVENT_FD_READ) { +- ares_process_fd(watch->ctx->channel, watch->fd, ARES_SOCKET_BAD); +- } +- if (flags & TEVENT_FD_WRITE) { +- ares_process_fd(watch->ctx->channel, ARES_SOCKET_BAD, watch->fd); +- } ++ ares_process_fd(watch->ctx->channel, ++ flags & TEVENT_FD_READ ? watch->fd : ARES_SOCKET_BAD, ++ flags & TEVENT_FD_WRITE ? watch->fd : ARES_SOCKET_BAD); + } + + static void +-- +2.9.3 + diff --git a/SPECS/sssd.spec b/SPECS/sssd.spec index 39bed2c..7cc3dc1 100644 --- a/SPECS/sssd.spec +++ b/SPECS/sssd.spec @@ -33,7 +33,7 @@ Name: sssd Version: 1.14.0 -Release: 43%{?dist}.4 +Release: 43%{?dist}.11 Group: Applications/System Summary: System Security Services Daemon License: GPLv3+ @@ -188,6 +188,15 @@ 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 +Patch0148: 0148-IPA-AD-check-auth-ctx-before-using-it.patch +Patch0149: 0149-Qualify-ghost-user-attribute-in-case-ldap_group_nest.patch +Patch0150: 0150-SYSDB-Split-sysdb_try_to_find_expected_dn-into-small.patch +Patch0151: 0151-SYSDB-Augment-sysdb_try_to_find_expected_dn-to-match.patch +Patch0152: 0152-SYSDB-Adding-lowercase-sudoUser-form.patch +Patch0153: 0153-SYSDB-Fixing-of-sudorule-without-a-sudoUser.patch +Patch0154: 0154-MONITOR-Do-not-set-up-watchdog-for-monitor.patch +Patch0155: 0155-AUTOFS-Fix-offline-resolution-of-autofs-maps.patch +Patch0156: 0156-Prevent-use-after-free-in-fd_input_available.patch #This patch should not be removed in RHEL-7 Patch999: 0999-NOUPSTREAM-Default-to-root-if-sssd-user-is-not-spec @@ -1182,6 +1191,32 @@ fi /usr/bin/rm -f /var/tmp/sssd.upgrade || : %changelog +* Tue Dec 13 2016 Jakub Hrozek - 1.14.0-43.11 +- Resolves: rhbz#1404340 - Use-after free in resolver in case the fd is + writeable and readable at the same time + +* Fri Nov 25 2016 Jakub Hrozek - 1.14.0-43.10 +- Resolves: rhbz#1398673 - autofs map resolution doesn't work offline + +* Thu Nov 24 2016 Jakub Hrozek - 1.14.0-43.9 +- Resolves: rhbz#1398169 - sssd fails to start after upgrading to RHEL 7.3 + +* Wed Nov 23 2016 Jakub Hrozek - 1.14.0-43.8 +- Resolves: rhbz#1392946 - sudo: ignore case on case insensitive domains + +* Wed Nov 23 2016 Jakub Hrozek - 1.14.0-43.7 +- Resolves: rhbz#1393730 - No supplementary groups are resolved for users + in nested OUs when domain stanza differs from AD + domain + +* Fri Nov 18 2016 Jakub Hrozek - 1.14.0-43.6 +- Related: rhbz#1396486 - bz - ldap group names don't resolve after + upgrading sssd to 1.14.0 if ldap_nesting_level + is set to 0 + +* Fri Nov 18 2016 Jakub Hrozek - 1.14.0-43.5 +- Related: rhbz#1396485 - sssd_be keeps crashing + * 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