diff --git a/SOURCES/0197-LDAP-AD-do-not-resolve-group-members-during-tokenGro.patch b/SOURCES/0197-LDAP-AD-do-not-resolve-group-members-during-tokenGro.patch new file mode 100644 index 0000000..3c458ee --- /dev/null +++ b/SOURCES/0197-LDAP-AD-do-not-resolve-group-members-during-tokenGro.patch @@ -0,0 +1,297 @@ +From b8d9eca0d9469c1209161b31a0109d8e4ea2868c Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Mon, 9 Mar 2015 16:36:29 +0100 +Subject: [PATCH] LDAP/AD: do not resolve group members during tokenGroups + request + +During initgroups requests we try to avoid to resolve the complete +member list of groups if possible, e.g. if there are no nested groups. +The tokenGroups LDAP lookup return the complete list of memberships for +a user hence it is not necessary lookup the other group member and +un-roll nested groups. With this patch only the group entry is looked up +and saved as incomplete group to the cache. + +This is achieved by adding a new boolean parameter no_members to +groups_get_send() and sdap_get_groups_send(). The difference to config +options like ldap_group_nesting_level = 0 or ignore_group_members is +that if no_members is set to true groups which are missing in the cache +are created a incomplete groups. As a result a request to lookup this +group will trigger a new LDAP request to resolve the group completely. +This way no information is ignored but the time needed to read all data +is better distributed between different requests. + +https://fedorahosted.org/sssd/ticket/2601 + +Reviewed-by: Jakub Hrozek +(cherry picked from commit d81d8d3dc151ebc95cd0e3f3b14c1cdaa48980f1) +--- + src/providers/ipa/ipa_subdomains_ext_groups.c | 2 +- + src/providers/ldap/ldap_common.h | 3 ++- + src/providers/ldap/ldap_id.c | 14 +++++++---- + src/providers/ldap/sdap_async.h | 3 ++- + src/providers/ldap/sdap_async_enum.c | 2 +- + src/providers/ldap/sdap_async_groups.c | 36 ++++++++++++++++++++++++++- + src/providers/ldap/sdap_async_initgroups.c | 14 +++++------ + src/providers/ldap/sdap_async_initgroups_ad.c | 2 +- + src/providers/ldap/sdap_async_private.h | 6 +++++ + 9 files changed, 64 insertions(+), 18 deletions(-) + +diff --git a/src/providers/ipa/ipa_subdomains_ext_groups.c b/src/providers/ipa/ipa_subdomains_ext_groups.c +index ad278b248ec2a2a157fed0a455dbe97049e83f9d..976a71cfe3ab42425e3884c5f6d9e096fe61bb34 100644 +--- a/src/providers/ipa/ipa_subdomains_ext_groups.c ++++ b/src/providers/ipa/ipa_subdomains_ext_groups.c +@@ -872,7 +872,7 @@ static void ipa_add_ad_memberships_get_next(struct tevent_req *req) + state->sdap_id_ctx->conn, + (const char *) val->data, + BE_FILTER_NAME, BE_ATTR_CORE, +- false); ++ false, false); + if (subreq == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "groups_get_send failed.\n"); + ret = ENOMEM; +diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h +index bf69489a79e903a98878edb53d372d2242df2b0f..57ad1b8458988d7e108f019c20f67bcde32539d4 100644 +--- a/src/providers/ldap/ldap_common.h ++++ b/src/providers/ldap/ldap_common.h +@@ -212,7 +212,8 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx, + const char *name, + int filter_type, + int attrs_type, +- bool noexist_delete); ++ bool noexist_delete, ++ bool no_members); + int groups_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret); + + struct tevent_req *ldap_netgroup_get_send(TALLOC_CTX *memctx, +diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c +index 6de5b72a8b66cd95b16d25a2c37dc21a57695de3..55bb3c9fbd6f623e7795d7399c9e5ac4d5192e85 100644 +--- a/src/providers/ldap/ldap_id.c ++++ b/src/providers/ldap/ldap_id.c +@@ -528,6 +528,7 @@ struct groups_get_state { + int dp_error; + int sdap_ret; + bool noexist_delete; ++ bool no_members; + }; + + static int groups_get_retry(struct tevent_req *req); +@@ -544,7 +545,8 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx, + const char *name, + int filter_type, + int attrs_type, +- bool noexist_delete) ++ bool noexist_delete, ++ bool no_members) + { + struct tevent_req *req; + struct groups_get_state *state; +@@ -567,6 +569,7 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx, + state->conn = conn; + state->dp_error = DP_ERR_FATAL; + state->noexist_delete = noexist_delete; ++ state->no_members = no_members; + + state->op = sdap_id_op_create(state, state->conn->conn_cache); + if (!state->op) { +@@ -713,7 +716,8 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx, + + /* TODO: handle attrs_type */ + ret = build_attrs_from_map(state, ctx->opts->group_map, SDAP_OPTS_GROUP, +- state->domain->ignore_group_members ? ++ (state->domain->ignore_group_members ++ || state->no_members) ? + (const char **)member_filter : NULL, + &state->attrs, NULL); + +@@ -845,7 +849,7 @@ static void groups_get_search(struct tevent_req *req) + state->attrs, state->filter, + dp_opt_get_int(state->ctx->opts->basic, + SDAP_SEARCH_TIMEOUT), +- false); ++ false, state->no_members); + if (!subreq) { + tevent_req_error(req, ENOMEM); + return; +@@ -1383,7 +1387,7 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx, + ar->filter_value, + ar->filter_type, + ar->attr_type, +- noexist_delete); ++ noexist_delete, false); + break; + + case BE_REQ_INITGROUPS: /* init groups for user */ +@@ -1718,7 +1722,7 @@ static struct tevent_req *get_user_and_group_send(TALLOC_CTX *memctx, + subreq = groups_get_send(req, state->ev, state->id_ctx, + state->sdom, state->conn, + state->filter_val, state->filter_type, +- state->attrs_type, state->noexist_delete); ++ state->attrs_type, state->noexist_delete, false); + if (subreq == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "users_get_send failed.\n"); + ret = ENOMEM; +diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h +index 1239f28c173373aac23c5796d694c7bd5ca24c96..ef9b3bbadba830bcf730b6fa70867c17d51380af 100644 +--- a/src/providers/ldap/sdap_async.h ++++ b/src/providers/ldap/sdap_async.h +@@ -96,7 +96,8 @@ struct tevent_req *sdap_get_groups_send(TALLOC_CTX *memctx, + const char **attrs, + const char *filter, + int timeout, +- bool enumeration); ++ bool enumeration, ++ bool no_members); + int sdap_get_groups_recv(struct tevent_req *req, + TALLOC_CTX *mem_ctx, char **timestamp); + +diff --git a/src/providers/ldap/sdap_async_enum.c b/src/providers/ldap/sdap_async_enum.c +index 242b3172f367b0b35738bd2e86ea927a4409d2d6..1cc09abdf1aa14e3d1690ea1abe32604ae4ff1cd 100644 +--- a/src/providers/ldap/sdap_async_enum.c ++++ b/src/providers/ldap/sdap_async_enum.c +@@ -811,7 +811,7 @@ static struct tevent_req *enum_groups_send(TALLOC_CTX *memctx, + state->attrs, state->filter, + dp_opt_get_int(state->ctx->opts->basic, + SDAP_ENUM_SEARCH_TIMEOUT), +- true); ++ true, false); + if (!subreq) { + ret = ENOMEM; + goto fail; +diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c +index c86b5c6b59a4de7e945b95cafae9149f681e2e18..818f30b95d4a4707c32d16b9866b008d89141e4d 100644 +--- a/src/providers/ldap/sdap_async_groups.c ++++ b/src/providers/ldap/sdap_async_groups.c +@@ -1750,6 +1750,7 @@ struct sdap_get_groups_state { + char *filter; + int timeout; + bool enumeration; ++ bool no_members; + + char *higher_usn; + struct sysdb_attrs **groups; +@@ -1779,7 +1780,8 @@ struct tevent_req *sdap_get_groups_send(TALLOC_CTX *memctx, + const char **attrs, + const char *filter, + int timeout, +- bool enumeration) ++ bool enumeration, ++ bool no_members) + { + errno_t ret; + struct tevent_req *req; +@@ -1802,6 +1804,7 @@ struct tevent_req *sdap_get_groups_send(TALLOC_CTX *memctx, + state->count = 0; + state->timeout = timeout; + state->enumeration = enumeration; ++ state->no_members = no_members; + state->base_filter = filter; + state->base_iter = 0; + state->search_bases = sdom->group_search_bases; +@@ -1926,6 +1929,7 @@ static void sdap_get_groups_process(struct tevent_req *subreq) + bool next_base = false; + size_t count; + struct sysdb_attrs **groups; ++ char **groupnamelist; + + ret = sdap_get_generic_recv(subreq, state, + &count, &groups); +@@ -1992,6 +1996,36 @@ static void sdap_get_groups_process(struct tevent_req *subreq) + return; + } + ++ if (state->no_members) { ++ ret = sysdb_attrs_primary_name_list(state->sysdb, state, ++ state->groups, state->count, ++ state->opts->group_map[SDAP_AT_GROUP_NAME].name, ++ &groupnamelist); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "sysdb_attrs_primary_name_list failed.\n"); ++ tevent_req_error(req, ret); ++ return; ++ } ++ ++ ret = sdap_add_incomplete_groups(state->sysdb, state->dom, state->opts, ++ groupnamelist, state->groups, ++ state->count); ++ if (ret == EOK) { ++ DEBUG(SSSDBG_TRACE_LIBS, ++ "Reading only group data without members successful.\n"); ++ tevent_req_done(req); ++ } else { ++ DEBUG(SSSDBG_OP_FAILURE, "sdap_add_incomplete_groups failed.\n"); ++ tevent_req_error(req, ret); ++ } ++ return; ++ ++ ret = sdap_save_groups(state, state->sysdb, state->dom, state->opts, ++ state->groups, state->count, false, ++ NULL, true, NULL); ++ } ++ + /* Check whether we need to do nested searches + * for RFC2307bis/FreeIPA/ActiveDirectory + * We don't need to do this for enumeration, +diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c +index 48c16b71637f83399d9a523f64f6d812b91681ef..2fd235f2868b877c0e5d5d9f7b1b76d269eee8ee 100644 +--- a/src/providers/ldap/sdap_async_initgroups.c ++++ b/src/providers/ldap/sdap_async_initgroups.c +@@ -29,12 +29,12 @@ + #include "providers/ldap/sdap_users.h" + + /* ==Save-fake-group-list=====================================*/ +-static errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb, +- struct sss_domain_info *domain, +- struct sdap_options *opts, +- char **groupnames, +- struct sysdb_attrs **ldap_groups, +- int ldap_groups_count) ++errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb, ++ struct sss_domain_info *domain, ++ struct sdap_options *opts, ++ char **groupnames, ++ struct sysdb_attrs **ldap_groups, ++ int ldap_groups_count) + { + TALLOC_CTX *tmp_ctx; + struct ldb_message *msg; +@@ -3152,7 +3152,7 @@ static void sdap_get_initgr_done(struct tevent_req *subreq) + + subreq = groups_get_send(req, state->ev, state->id_ctx, + state->id_ctx->opts->sdom, state->conn, +- gid, BE_FILTER_IDNUM, BE_ATTR_ALL, NULL); ++ gid, BE_FILTER_IDNUM, BE_ATTR_ALL, false, false); + if (!subreq) { + ret = ENOMEM; + goto fail; +diff --git a/src/providers/ldap/sdap_async_initgroups_ad.c b/src/providers/ldap/sdap_async_initgroups_ad.c +index 1b8c8d981ea14ac0fca0903f16296c8a6701c5dd..9915f1863f172d5d3f59afe03abbbfb87fdf3409 100644 +--- a/src/providers/ldap/sdap_async_initgroups_ad.c ++++ b/src/providers/ldap/sdap_async_initgroups_ad.c +@@ -630,7 +630,7 @@ static errno_t sdap_ad_resolve_sids_step(struct tevent_req *req) + + subreq = groups_get_send(state, state->ev, state->id_ctx, sdap_domain, + state->conn, state->current_sid, +- BE_FILTER_SECID, BE_ATTR_CORE, false); ++ BE_FILTER_SECID, BE_ATTR_CORE, false, true); + if (subreq == NULL) { + return ENOMEM; + } +diff --git a/src/providers/ldap/sdap_async_private.h b/src/providers/ldap/sdap_async_private.h +index e689394c5db8a3385c333e6b98372c6f6d34366c..3995a2ac357c52f546696284d71d2127d0302409 100644 +--- a/src/providers/ldap/sdap_async_private.h ++++ b/src/providers/ldap/sdap_async_private.h +@@ -132,4 +132,10 @@ errno_t sdap_nested_group_recv(TALLOC_CTX *mem_ctx, + unsigned long *_num_groups, + struct sysdb_attrs ***_groups); + ++errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb, ++ struct sss_domain_info *domain, ++ struct sdap_options *opts, ++ char **groupnames, ++ struct sysdb_attrs **ldap_groups, ++ int ldap_groups_count); + #endif /* _SDAP_ASYNC_PRIVATE_H_ */ +-- +2.1.0 + diff --git a/SOURCES/0198-SDAP-Do-not-set-gid-0-twice.patch b/SOURCES/0198-SDAP-Do-not-set-gid-0-twice.patch new file mode 100644 index 0000000..a6c60ee --- /dev/null +++ b/SOURCES/0198-SDAP-Do-not-set-gid-0-twice.patch @@ -0,0 +1,49 @@ +From 63209a5d62f2ef1a184b5d1799a27bab8278f43a Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Fri, 10 Apr 2015 14:33:35 +0200 +Subject: [PATCH 198/200] SDAP: Do not set gid 0 twice + +The gid o was added to sysdb attrs directly in sdap_save_group for 1st time +and for second time in the function sdap_store_group_with_gid, +which was called every time from function sdap_save_group + +[sysdb_set_entry_attr] (0x0080): ldb_modify failed: + [Attribute or value exists](20)[attribute 'gidNumber': value #1 + on 'name=domainlocalgroup1_dom2-493341@sssdad_tree.com,cn=groups,cn=sssdad_tree.com,cn=sysdb' provided more than once] +[sysdb_set_entry_attr] (0x0040): Error: 17 (File exists) +[sysdb_store_group] (0x1000): sysdb_set_group_attr failed. +[sysdb_store_group] (0x0400): Error: 17 (File exists) +[sdap_store_group_with_gid] (0x0040): + Could not store group domainlocalgroup1_dom2-493341@sssdad_tree.com +[sdap_save_group] (0x0080): Could not store group with GID: [File exists] +[sdap_save_group] (0x0080): + Failed to save group [domainlocalgroup1_dom2-493341@sssdad_tree.com]: [File exists] +[sdap_save_groups] (0x0040): Failed to store group 0. Ignoring. + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 5d864e7a9d0e1e6fb7dd8158c5b8bfb71040b908) +--- + src/providers/ldap/sdap_async_groups.c | 7 ------- + 1 file changed, 7 deletions(-) + +diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c +index 818f30b95d4a4707c32d16b9866b008d89141e4d..4be8c502ea77a3913ddac2a24fbacbc522b2ef6b 100644 +--- a/src/providers/ldap/sdap_async_groups.c ++++ b/src/providers/ldap/sdap_async_groups.c +@@ -608,13 +608,6 @@ static int sdap_save_group(TALLOC_CTX *memctx, + gid = 0; + DEBUG(SSSDBG_TRACE_FUNC, "Filtering AD group [%s].\n", + group_name); +- ret = sysdb_attrs_add_uint32(group_attrs, +- opts->group_map[SDAP_AT_GROUP_GID].sys_name, 0); +- if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, +- "Failed to add a GID to non-posix group!\n"); +- return ret; +- } + ret = sysdb_attrs_add_bool(group_attrs, SYSDB_POSIX, false); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, +-- +2.1.0 + diff --git a/SOURCES/0199-SDAP-Extract-filtering-AD-group-to-function.patch b/SOURCES/0199-SDAP-Extract-filtering-AD-group-to-function.patch new file mode 100644 index 0000000..263918e --- /dev/null +++ b/SOURCES/0199-SDAP-Extract-filtering-AD-group-to-function.patch @@ -0,0 +1,240 @@ +From 64eb7055b640e9c92701886effc36f74fe9e709f Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Mon, 13 Apr 2015 09:44:35 +0200 +Subject: [PATCH 199/200] SDAP: Extract filtering AD group to function + +Patch remove code duplication. + +Reviewed-by: Jakub Hrozek +(cherry picked from commit bad2fc8133d941e5a6c8d8016c9689e039265c61) +--- + Makefile.am | 2 + + src/providers/ldap/sdap_ad_groups.c | 68 +++++++++++++++++++++++++++ + src/providers/ldap/sdap_async_groups.c | 40 ++++++---------- + src/providers/ldap/sdap_async_nested_groups.c | 31 ++++-------- + src/providers/ldap/sdap_async_private.h | 7 +++ + 5 files changed, 101 insertions(+), 47 deletions(-) + create mode 100644 src/providers/ldap/sdap_ad_groups.c + +diff --git a/Makefile.am b/Makefile.am +index 8202659e0933529ca7911952bbf1476dbb4a76fc..f402239af2cfaf77dde1ce6ff261015f5d9bfacc 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -1858,6 +1858,7 @@ nestedgroups_tests_SOURCES = \ + src/providers/ldap/sdap_idmap.c \ + src/tests/cmocka/test_nested_groups.c \ + src/providers/ldap/sdap_async_nested_groups.c \ ++ src/providers/ldap/sdap_ad_groups.c \ + $(NULL) + nestedgroups_tests_CFLAGS = \ + $(AM_CFLAGS) \ +@@ -2307,6 +2308,7 @@ libsss_ldap_common_la_SOURCES = \ + src/providers/ldap/sdap_async_connection.c \ + src/providers/ldap/sdap_async_netgroups.c \ + src/providers/ldap/sdap_async_services.c \ ++ src/providers/ldap/sdap_ad_groups.c \ + src/providers/ldap/sdap_child_helpers.c \ + src/providers/ldap/sdap_fd_events.c \ + src/providers/ldap/sdap_id_op.c \ +diff --git a/src/providers/ldap/sdap_ad_groups.c b/src/providers/ldap/sdap_ad_groups.c +new file mode 100644 +index 0000000000000000000000000000000000000000..0e36328b9b52643a2ec698b2a41f2a56a8ff69b6 +--- /dev/null ++++ b/src/providers/ldap/sdap_ad_groups.c +@@ -0,0 +1,68 @@ ++/* ++ SSSD ++ ++ AD groups helper routines ++ ++ Authors: ++ Lukas Slebodnik ++ ++ Copyright (C) 2013 Red Hat ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . ++*/ ++ ++#include "db/sysdb.h" ++#include "providers/ldap/sdap.h" ++#include "providers/ldap/sdap_async_private.h" ++ ++/* ==Group-Parsing Routines=============================================== */ ++ ++errno_t sdap_check_ad_group_type(struct sss_domain_info *dom, ++ struct sdap_options *opts, ++ struct sysdb_attrs *group_attrs, ++ const char *group_name, ++ bool *_need_filter) ++{ ++ int32_t ad_group_type; ++ errno_t ret = EOK; ++ *_need_filter = false; ++ ++ if (opts->schema_type == SDAP_SCHEMA_AD) { ++ ret = sysdb_attrs_get_int32_t(group_attrs, SYSDB_GROUP_TYPE, ++ &ad_group_type); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_int32_t failed.\n"); ++ return ret; ++ } ++ ++ DEBUG(SSSDBG_TRACE_ALL, ++ "AD group [%s] has type flags %#x.\n", ++ group_name, ad_group_type); ++ ++ /* Only security groups from AD are considered for POSIX groups. ++ * Additionally only global and universal group are taken to account ++ * for trusted domains. */ ++ if (!(ad_group_type & SDAP_AD_GROUP_TYPE_SECURITY) ++ || (IS_SUBDOMAIN(dom) ++ && (!((ad_group_type & SDAP_AD_GROUP_TYPE_GLOBAL) ++ || (ad_group_type & SDAP_AD_GROUP_TYPE_UNIVERSAL))))) { ++ DEBUG(SSSDBG_TRACE_FUNC, ++ "Filtering AD group [%s].\n", group_name); ++ ++ *_need_filter = true; ++ } ++ } ++ ++ return ret; ++} +diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c +index 4be8c502ea77a3913ddac2a24fbacbc522b2ef6b..00a676372fa042dfc2d57e5799261f9a45ed4a73 100644 +--- a/src/providers/ldap/sdap_async_groups.c ++++ b/src/providers/ldap/sdap_async_groups.c +@@ -510,10 +510,10 @@ static int sdap_save_group(TALLOC_CTX *memctx, + TALLOC_CTX *tmpctx = NULL; + bool posix_group; + bool use_id_mapping; ++ bool need_filter; + char *sid_str; + const char *uuid; + struct sss_domain_info *subdomain; +- int32_t ad_group_type; + + tmpctx = talloc_new(NULL); + if (!tmpctx) { +@@ -588,32 +588,20 @@ static int sdap_save_group(TALLOC_CTX *memctx, + DEBUG(SSSDBG_TRACE_FUNC, "Processing group %s\n", group_name); + + posix_group = true; +- if (opts->schema_type == SDAP_SCHEMA_AD) { +- ret = sysdb_attrs_get_int32_t(attrs, SYSDB_GROUP_TYPE, &ad_group_type); +- if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_int32_t failed.\n"); +- goto done; +- } ++ ret = sdap_check_ad_group_type(dom, opts, attrs, group_name, ++ &need_filter); ++ if (ret != EOK) { ++ goto done; ++ } ++ if (need_filter) { ++ posix_group = false; ++ gid = 0; + +- DEBUG(SSSDBG_TRACE_ALL, "AD group [%s] has type flags %#x.\n", +- group_name, ad_group_type); +- /* Only security groups from AD are considered for POSIX groups. +- * Additionally only global and universal group are taken to account +- * for trusted domains. */ +- if (!(ad_group_type & SDAP_AD_GROUP_TYPE_SECURITY) +- || (IS_SUBDOMAIN(dom) +- && (!((ad_group_type & SDAP_AD_GROUP_TYPE_GLOBAL) +- || (ad_group_type & SDAP_AD_GROUP_TYPE_UNIVERSAL))))) { +- posix_group = false; +- gid = 0; +- DEBUG(SSSDBG_TRACE_FUNC, "Filtering AD group [%s].\n", +- group_name); +- ret = sysdb_attrs_add_bool(group_attrs, SYSDB_POSIX, false); +- if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, +- "Error: Failed to mark group as non-posix!\n"); +- return ret; +- } ++ ret = sysdb_attrs_add_bool(group_attrs, SYSDB_POSIX, false); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "Error: Failed to mark group as non-posix!\n"); ++ return ret; + } + } + +diff --git a/src/providers/ldap/sdap_async_nested_groups.c b/src/providers/ldap/sdap_async_nested_groups.c +index 1eba35ae8ac90acac8a2d46e8cc5f2b57e3a9256..08e199869ad16c3b19d998a2a28eae9a0dd0a371 100644 +--- a/src/providers/ldap/sdap_async_nested_groups.c ++++ b/src/providers/ldap/sdap_async_nested_groups.c +@@ -240,32 +240,21 @@ sdap_nested_group_hash_group(struct sdap_nested_group_ctx *group_ctx, + { + struct sdap_attr_map *map = group_ctx->opts->group_map; + gid_t gid; +- errno_t ret = ENOENT; +- int32_t ad_group_type; ++ errno_t ret; + bool posix_group = true; + bool use_id_mapping; + bool can_find_gid; ++ bool need_filter; + +- if (group_ctx->opts->schema_type == SDAP_SCHEMA_AD) { +- ret = sysdb_attrs_get_int32_t(group, SYSDB_GROUP_TYPE, &ad_group_type); +- if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_int32_t failed.\n"); +- return ret; +- } ++ ret = sdap_check_ad_group_type(group_ctx->domain, group_ctx->opts, ++ group, "", &need_filter); ++ if (ret != EOK) { ++ return ret; ++ } + +- DEBUG(SSSDBG_TRACE_ALL, "AD group has type flags %#x.\n", +- ad_group_type); +- /* Only security groups from AD are considered for POSIX groups. +- * Additionally only global and universal group are taken to account +- * for trusted domains. */ +- if (!(ad_group_type & SDAP_AD_GROUP_TYPE_SECURITY) +- || (IS_SUBDOMAIN(group_ctx->domain) +- && (!((ad_group_type & SDAP_AD_GROUP_TYPE_GLOBAL) +- || (ad_group_type & SDAP_AD_GROUP_TYPE_UNIVERSAL))))) { +- posix_group = false; +- gid = 0; +- DEBUG(SSSDBG_TRACE_FUNC, "Filtering AD group.\n"); +- } ++ if (need_filter) { ++ posix_group = false; ++ gid = 0; + } + + use_id_mapping = sdap_idmap_domain_has_algorithmic_mapping( +diff --git a/src/providers/ldap/sdap_async_private.h b/src/providers/ldap/sdap_async_private.h +index 3995a2ac357c52f546696284d71d2127d0302409..db542eaf869efcd53d0937bef3fc6e99cc78b938 100644 +--- a/src/providers/ldap/sdap_async_private.h ++++ b/src/providers/ldap/sdap_async_private.h +@@ -138,4 +138,11 @@ errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb, + char **groupnames, + struct sysdb_attrs **ldap_groups, + int ldap_groups_count); ++ ++/* from sdap_async_nested_groups.c */ ++errno_t sdap_check_ad_group_type(struct sss_domain_info *dom, ++ struct sdap_options *opts, ++ struct sysdb_attrs *group_attrs, ++ const char *group_name, ++ bool *_need_filter); + #endif /* _SDAP_ASYNC_PRIVATE_H_ */ +-- +2.1.0 + diff --git a/SOURCES/0200-SDAP-Filter-ad-groups-in-initgroups.patch b/SOURCES/0200-SDAP-Filter-ad-groups-in-initgroups.patch new file mode 100644 index 0000000..42b8547 --- /dev/null +++ b/SOURCES/0200-SDAP-Filter-ad-groups-in-initgroups.patch @@ -0,0 +1,50 @@ +From bea6b6c6bcf711e0d96a4263f60e0e1b0a64c45f Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Mon, 13 Apr 2015 09:50:29 +0200 +Subject: [PATCH 200/200] SDAP: Filter ad groups in initgroups + +Function sdap_add_incomplete_groups stored domain local groups +from subdomain as POSIX group, which should not be done. + +Resolves: +https://fedorahosted.org/sssd/ticket/2614 + +Reviewed-by: Jakub Hrozek +(cherry picked from commit b9fbeb75e7a4f50f98d979a70a710f9221892483) +--- + src/providers/ldap/sdap_async_initgroups.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c +index bc6b5e45e6a7f7dc0c482a6bbbf2aa602371a647..43b72fe2051b452c6ea755c8842117cceafa143a 100644 +--- a/src/providers/ldap/sdap_async_initgroups.c ++++ b/src/providers/ldap/sdap_async_initgroups.c +@@ -51,6 +51,7 @@ errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb, + time_t now; + char *sid_str = NULL; + bool use_id_mapping; ++ bool need_filter; + char *tmp_name; + + /* There are no groups in LDAP but we should add user to groups ?? */ +@@ -205,6 +206,17 @@ errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb, + uuid = NULL; + } + ++ ret = sdap_check_ad_group_type(domain, opts, ldap_groups[ai], ++ groupname, &need_filter); ++ if (ret != EOK) { ++ goto done; ++ } ++ ++ if (need_filter) { ++ posix = false; ++ gid = 0; ++ } ++ + DEBUG(SSSDBG_TRACE_INTERNAL, + "Adding fake group %s to sysdb\n", groupname); + ret = sysdb_add_incomplete_group(domain, groupname, gid, +-- +2.1.0 + diff --git a/SOURCES/0201-sdap-properly-handle-binary-objectGuid-attribute.patch b/SOURCES/0201-sdap-properly-handle-binary-objectGuid-attribute.patch new file mode 100644 index 0000000..35ba8ec --- /dev/null +++ b/SOURCES/0201-sdap-properly-handle-binary-objectGuid-attribute.patch @@ -0,0 +1,501 @@ +From 745cf4cc7f4e8f7cdc6ea74b5c39a70f0201a883 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Tue, 17 Feb 2015 04:41:21 +0100 +Subject: [PATCH 201/207] sdap: properly handle binary objectGuid attribute + +Although in the initial processing SSSD treats the binary value right at +some point it mainly assumes that it is a string. Depending on the value +this might end up with the correct binary value stored in the cache but +in most cases there will be only a broken entry in the cache. + +This patch converts the binary value into a string representation which +is described in [MS-DTYP] and stores the result in the cache. + +Resolves https://fedorahosted.org/sssd/ticket/2588 + +Reviewed-by: Jakub Hrozek +--- + src/db/sysdb.h | 6 ++ + src/db/sysdb_ops.c | 52 +++++++++++ + src/providers/ldap/sdap_async_groups.c | 25 ++---- + src/providers/ldap/sdap_async_initgroups.c | 7 +- + src/providers/ldap/sdap_async_users.c | 23 ++--- + src/tests/cmocka/test_string_utils.c | 59 +++++++++++++ + src/tests/cmocka/test_sysdb_utils.c | 134 +++++++++++++++++++++++++++++ + src/tests/cmocka/test_utils.h | 1 + + src/tests/cwrap/Makefile.am | 2 + + src/util/string_utils.c | 25 ++++++ + src/util/util.h | 7 ++ + 11 files changed, 307 insertions(+), 34 deletions(-) + create mode 100644 src/tests/cmocka/test_sysdb_utils.c + +diff --git a/src/db/sysdb.h b/src/db/sysdb.h +index cf6028acb806d5d4eedf4cf0680cf4ac9fd6368d..ee5757130ec24a4ddfef854af5f59fc3ccc5b8ae 100644 +--- a/src/db/sysdb.h ++++ b/src/db/sysdb.h +@@ -1113,4 +1113,10 @@ errno_t sysdb_get_sids_of_members(TALLOC_CTX *mem_ctx, + const char ***_sids, + const char ***_dns, + size_t *_n); ++ ++errno_t sysdb_handle_original_uuid(const char *orig_name, ++ struct sysdb_attrs *src_attrs, ++ const char *src_name, ++ struct sysdb_attrs *dest_attrs, ++ const char *dest_name); + #endif /* __SYS_DB_H__ */ +diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c +index 6085762dcc5585114dd3049dd3a365856cb6b190..7e1c1d9763a04cd33374770f4ea5d51286bcfee2 100644 +--- a/src/db/sysdb_ops.c ++++ b/src/db/sysdb_ops.c +@@ -3670,3 +3670,55 @@ done: + talloc_free(tmp_ctx); + return ret; + } ++ ++errno_t sysdb_handle_original_uuid(const char *orig_name, ++ struct sysdb_attrs *src_attrs, ++ const char *src_name, ++ struct sysdb_attrs *dest_attrs, ++ const char *dest_name) ++{ ++ int ret; ++ struct ldb_message_element *el; ++ char guid_str_buf[GUID_STR_BUF_SIZE]; ++ ++ if (orig_name == NULL || src_attrs == NULL || src_name == NULL ++ || dest_attrs == NULL || dest_name == NULL) { ++ return EINVAL; ++ } ++ ++ ret = sysdb_attrs_get_el_ext(src_attrs, src_name, false, &el); ++ if (ret != EOK) { ++ if (ret != ENOENT) { ++ DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_get_el failed.\n"); ++ } ++ return ret; ++ } ++ ++ if (el->num_values != 1) { ++ DEBUG(SSSDBG_MINOR_FAILURE, ++ "Found more than one UUID value, using the first.\n"); ++ } ++ ++ /* Check if we got a binary AD objectGUID */ ++ if (el->values[0].length == GUID_BIN_LENGTH ++ && strcasecmp(orig_name, "objectGUID") == 0) { ++ ret = guid_blob_to_string_buf(el->values[0].data, guid_str_buf, ++ GUID_STR_BUF_SIZE); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, "guid_blob_to_string_buf failed.\n"); ++ return ret; ++ } ++ ++ ret = sysdb_attrs_add_string(dest_attrs, dest_name, guid_str_buf); ++ } else { ++ ret = sysdb_attrs_add_string(dest_attrs, dest_name, ++ (const char *)el->values[0].data); ++ } ++ ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, "sysdb_attrs_add_string failed.\n"); ++ return ret;; ++ } ++ ++ return EOK; ++} +diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c +index 00a676372fa042dfc2d57e5799261f9a45ed4a73..1714188bee681ff70a03db741cf50058f145abbe 100644 +--- a/src/providers/ldap/sdap_async_groups.c ++++ b/src/providers/ldap/sdap_async_groups.c +@@ -512,7 +512,6 @@ static int sdap_save_group(TALLOC_CTX *memctx, + bool use_id_mapping; + bool need_filter; + char *sid_str; +- const char *uuid; + struct sss_domain_info *subdomain; + + tmpctx = talloc_new(NULL); +@@ -549,22 +548,14 @@ static int sdap_save_group(TALLOC_CTX *memctx, + } + + /* Always store UUID if available */ +- ret = sysdb_attrs_get_string(attrs, +- opts->group_map[SDAP_AT_GROUP_UUID].sys_name, +- &uuid); +- if (ret == EOK) { +- ret = sysdb_attrs_add_string(group_attrs, SYSDB_UUID, uuid); +- if (ret != EOK) { +- DEBUG(SSSDBG_MINOR_FAILURE, "Could not add UUID string: [%s]\n", +- sss_strerror(ret)); +- goto done; +- } +- } else if (ret == ENOENT) { +- DEBUG(SSSDBG_TRACE_ALL, "UUID not available for group [%s].\n", +- group_name); +- } else { +- DEBUG(SSSDBG_MINOR_FAILURE, "Could not identify UUID [%s]\n", +- sss_strerror(ret)); ++ ret = sysdb_handle_original_uuid( ++ opts->group_map[SDAP_AT_GROUP_UUID].def_name, ++ attrs, ++ opts->group_map[SDAP_AT_GROUP_UUID].sys_name, ++ group_attrs, SYSDB_UUID); ++ if (ret != EOK) { ++ DEBUG((ret == ENOENT) ? SSSDBG_TRACE_ALL : SSSDBG_MINOR_FAILURE, ++ "Failed to retrieve UUID [%d][%s].\n", ret, sss_strerror(ret)); + } + + /* If this object has a SID available, we will determine the correct +diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c +index 43b72fe2051b452c6ea755c8842117cceafa143a..416d2a9594e456b159f24c224fdd8bf8617377d7 100644 +--- a/src/providers/ldap/sdap_async_initgroups.c ++++ b/src/providers/ldap/sdap_async_initgroups.c +@@ -197,8 +197,13 @@ errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb, + original_dn = NULL; + } + ++ ret = sysdb_handle_original_uuid( ++ opts->group_map[SDAP_AT_GROUP_UUID].def_name, ++ ldap_groups[ai], ++ opts->group_map[SDAP_AT_GROUP_UUID].sys_name, ++ ldap_groups[ai], "uniqueIDstr"); + ret = sysdb_attrs_get_string(ldap_groups[ai], +- SYSDB_UUID, ++ "uniqueIDstr", + &uuid); + if (ret) { + DEBUG(SSSDBG_FUNC_DATA, +diff --git a/src/providers/ldap/sdap_async_users.c b/src/providers/ldap/sdap_async_users.c +index 367e3d795ddd0db5c1c2f8e57d700419f371cd15..82b4df4793f5f0679046f259c251f5897af831cf 100644 +--- a/src/providers/ldap/sdap_async_users.c ++++ b/src/providers/ldap/sdap_async_users.c +@@ -140,7 +140,6 @@ int sdap_save_user(TALLOC_CTX *memctx, + TALLOC_CTX *tmpctx = NULL; + bool use_id_mapping; + char *sid_str; +- const char *uuid; + char *dom_sid_str = NULL; + struct sss_domain_info *subdomain; + +@@ -179,21 +178,13 @@ int sdap_save_user(TALLOC_CTX *memctx, + } + + /* Always store UUID if available */ +- ret = sysdb_attrs_get_string(attrs, +- opts->user_map[SDAP_AT_USER_UUID].sys_name, +- &uuid); +- if (ret == EOK) { +- ret = sysdb_attrs_add_string(user_attrs, SYSDB_UUID, uuid); +- if (ret != EOK) { +- DEBUG(SSSDBG_MINOR_FAILURE, "Could not add UUID string: [%s]\n", +- sss_strerror(ret)); +- goto done; +- } +- } else if (ret == ENOENT) { +- DEBUG(SSSDBG_TRACE_ALL, "UUID not available for user.\n"); +- } else { +- DEBUG(SSSDBG_MINOR_FAILURE, "Could not identify UUID [%s]\n", +- sss_strerror(ret)); ++ ret = sysdb_handle_original_uuid(opts->user_map[SDAP_AT_USER_UUID].def_name, ++ attrs, ++ opts->user_map[SDAP_AT_USER_UUID].sys_name, ++ user_attrs, SYSDB_UUID); ++ if (ret != EOK) { ++ DEBUG((ret == ENOENT) ? SSSDBG_TRACE_ALL : SSSDBG_MINOR_FAILURE, ++ "Failed to retrieve UUID [%d][%s].\n", ret, sss_strerror(ret)); + } + + /* If this object has a SID available, we will determine the correct +diff --git a/src/tests/cmocka/test_string_utils.c b/src/tests/cmocka/test_string_utils.c +index e446387d6c429515360b23b428555befa915b49a..5d3fcf4fe454a0be3a4c72b778003481f66910bb 100644 +--- a/src/tests/cmocka/test_string_utils.c ++++ b/src/tests/cmocka/test_string_utils.c +@@ -133,3 +133,62 @@ void test_reverse_replace_whitespaces(void **state) + assert_true(check_leaks_pop(mem_ctx) == true); + talloc_free(mem_ctx); + } ++ ++void test_guid_blob_to_string_buf(void **state) ++{ ++ int ret; ++ char str_buf[GUID_STR_BUF_SIZE]; ++ size_t c; ++ ++ /* How to get test data: ++ * The objectGUID attribute contains a 16byte long binary value ++ * representing the GUID of the object. This data can be converted ++ * manually to the string representation but it might be easier to use ++ * LDAP_SERVER_EXTENDED_DN_OID as described in [MS-ADST] section ++ * 3.1.1.3.4.1.5. This is an LDAP extended control which adds the GUID and ++ * the SID to the DN of an object. This can be activate with the -E ++ * ldapsearch option like: ++ * ++ * ldapsearch -E 1.2.840.113556.1.4.529=::MAMCAQE= .... ++ * ++ * where 'MAMCAQE=' is the base64 encoded BER sequence with the integer ++ * value 1 (see [MS-ADTS] for details about possible values). ++ * ++ * Btw, if you want to use the string representation of a GUID to search ++ * for an object in AD you have to use the GUID as the search base in the ++ * following form: ++ * ++ * ldapsearch b '' ... ++ * ++ * (please note that the '<' and '>' are really needed). ++ */ ++ struct test_data { ++ uint8_t blob[16]; ++ const char *guid_str; ++ } test_data[] = { ++ {{0x8d, 0x0d, 0xa8, 0xfe, 0xd5, 0xdb, 0x84, 0x4f, ++ 0x85, 0x74, 0x7d, 0xb0, 0x47, 0x7f, 0x96, 0x2e}, ++ "fea80d8d-dbd5-4f84-8574-7db0477f962e"}, ++ {{0x91, 0x7e, 0x2e, 0xf8, 0x4e, 0x44, 0xfa, 0x4e, ++ 0xb1, 0x13, 0x08, 0x98, 0x63, 0x49, 0x6c, 0xc6}, ++ "f82e7e91-444e-4efa-b113-089863496cc6"}, ++ {{0}, NULL} ++ }; ++ ++ ret = guid_blob_to_string_buf(NULL, str_buf, GUID_STR_BUF_SIZE); ++ assert_int_equal(ret, EINVAL); ++ ++ ret = guid_blob_to_string_buf((const uint8_t *) "1234567812345678", NULL, ++ GUID_STR_BUF_SIZE); ++ assert_int_equal(ret, EINVAL); ++ ++ ret = guid_blob_to_string_buf((const uint8_t *) "1234567812345678", str_buf, 0); ++ assert_int_equal(ret, EINVAL); ++ ++ for (c = 0; test_data[c].guid_str != NULL; c++) { ++ ret = guid_blob_to_string_buf(test_data[c].blob, str_buf, ++ sizeof(str_buf)); ++ assert_int_equal(ret, EOK); ++ assert_string_equal(test_data[c].guid_str, str_buf); ++ } ++} +diff --git a/src/tests/cmocka/test_sysdb_utils.c b/src/tests/cmocka/test_sysdb_utils.c +new file mode 100644 +index 0000000000000000000000000000000000000000..d217314ccb9234f8d0d329d87c5dc9e847acbcf0 +--- /dev/null ++++ b/src/tests/cmocka/test_sysdb_utils.c +@@ -0,0 +1,134 @@ ++/* ++ SSSD ++ ++ sysdb_utils - Tests for various sysdb calls ++ ++ Authors: ++ Sumit Bose ++ ++ Copyright (C) 2015 Red Hat ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "tests/cmocka/common_mock.h" ++ ++#define IPA_UUID "bcae7c40-97eb-11e4-88ca-525400e96a6b" ++ ++#define AD_GUID_BIN {0x8d, 0x0d, 0xa8, 0xfe, 0xd5, 0xdb, 0x84, 0x4f, \ ++ 0x85, 0x74, 0x7d, 0xb0, 0x47, 0x7f, 0x96, 0x2e}; ++#define AD_GUID "fea80d8d-dbd5-4f84-8574-7db0477f962e" ++static void test_sysdb_handle_original_uuid(void **state) ++{ ++ int ret; ++ struct sysdb_attrs *src_attrs; ++ struct sysdb_attrs *dest_attrs; ++ const char *guid; ++ uint8_t bin_guid[] = AD_GUID_BIN; ++ struct ldb_val guid_val = {bin_guid, 16}; ++ ++ ret = sysdb_handle_original_uuid(NULL, NULL, NULL, NULL, NULL); ++ assert_int_equal(ret, EINVAL); ++ ++ src_attrs = sysdb_new_attrs(NULL); ++ assert_non_null(src_attrs); ++ ++ dest_attrs = sysdb_new_attrs(NULL); ++ assert_non_null(dest_attrs); ++ ++ ret = sysdb_handle_original_uuid("xyz", src_attrs, "abc", dest_attrs, ++ "def"); ++ assert_int_equal(ret, ENOENT); ++ ++ ret = sysdb_attrs_add_val(src_attrs, "GUID", &guid_val); ++ assert_int_equal(ret, EOK); ++ ++ ret = sysdb_attrs_add_string(src_attrs, "UUID", IPA_UUID); ++ assert_int_equal(ret, EOK); ++ ++ ret = sysdb_handle_original_uuid("objectGUID", src_attrs, "GUID", ++ dest_attrs, "def"); ++ assert_int_equal(ret, EOK); ++ ret = sysdb_attrs_get_string(dest_attrs, "def", &guid); ++ assert_int_equal(ret, EOK); ++ assert_string_equal(guid, AD_GUID); ++ ++ ret = sysdb_handle_original_uuid("ipaUniqueID", src_attrs, "UUID", ++ dest_attrs, "ghi"); ++ assert_int_equal(ret, EOK); ++ ret = sysdb_attrs_get_string(dest_attrs, "ghi", &guid); ++ assert_int_equal(ret, EOK); ++ assert_string_equal(guid, IPA_UUID); ++ ++ talloc_free(src_attrs); ++ src_attrs = sysdb_new_attrs(NULL); ++ assert_non_null(src_attrs); ++ ++ /* check objectGUID with length other than 16 */ ++ ret = sysdb_attrs_add_string(src_attrs, "GUID", IPA_UUID); ++ assert_int_equal(ret, EOK); ++ ret = sysdb_handle_original_uuid("objectGUID", src_attrs, "GUID", ++ dest_attrs, "jkl"); ++ assert_int_equal(ret, EOK); ++ ret = sysdb_attrs_get_string(dest_attrs, "jkl", &guid); ++ assert_int_equal(ret, EOK); ++ assert_string_equal(guid, IPA_UUID); ++ ++ talloc_free(src_attrs); ++ talloc_free(dest_attrs); ++} ++ ++int main(int argc, const char *argv[]) ++{ ++ int rv; ++ poptContext pc; ++ int opt; ++ struct poptOption long_options[] = { ++ POPT_AUTOHELP ++ SSSD_DEBUG_OPTS ++ POPT_TABLEEND ++ }; ++ ++ const UnitTest tests[] = { ++ unit_test(test_sysdb_handle_original_uuid), ++ }; ++ ++ /* Set debug level to invalid value so we can deside if -d 0 was used. */ ++ debug_level = SSSDBG_INVALID; ++ ++ pc = poptGetContext(argv[0], argc, argv, long_options, 0); ++ while((opt = poptGetNextOpt(pc)) != -1) { ++ switch(opt) { ++ default: ++ fprintf(stderr, "\nInvalid option %s: %s\n\n", ++ poptBadOption(pc, 0), poptStrerror(opt)); ++ poptPrintUsage(pc, stderr, 0); ++ return 1; ++ } ++ } ++ poptFreeContext(pc); ++ ++ DEBUG_CLI_INIT(debug_level); ++ ++ tests_set_cwd(); ++ rv = run_tests(tests); ++ ++ return rv; ++} +diff --git a/src/tests/cmocka/test_utils.h b/src/tests/cmocka/test_utils.h +index f85ac2f2b3c50a60099970752b06adbad38b9fd1..61ef7e43a82649d775d9b932def9e957b0761bed 100644 +--- a/src/tests/cmocka/test_utils.h ++++ b/src/tests/cmocka/test_utils.h +@@ -29,5 +29,6 @@ void test_textual_public_key(void **state); + /* from src/tests/cmocka/test_string_utils.c */ + void test_replace_whitespaces(void **state); + void test_reverse_replace_whitespaces(void **state); ++void test_guid_blob_to_string_buf(void **state); + + #endif /* __TESTS__CMOCKA__TEST_UTILS_H__ */ +diff --git a/src/tests/cwrap/Makefile.am b/src/tests/cwrap/Makefile.am +index 46abab5ae32189b0561d1901407d2bb38a1ec4c0..7e603fda15024da71cf57912acc69bddcc882357 100644 +--- a/src/tests/cwrap/Makefile.am ++++ b/src/tests/cwrap/Makefile.am +@@ -78,6 +78,7 @@ server_tests_SOURCES = \ + ../../../src/util/atomic_io.c \ + ../../../src/util/signal.c \ + ../../../src/util/util.c \ ++ ../../../src/util/string_utils.c \ + ../../../src/util/strtonum.c \ + ../../../src/util/util_errors.c \ + ../../../src/util/safe-format-string.c \ +@@ -115,6 +116,7 @@ usertools_tests_SOURCES = \ + ../../../src/util/domain_info_utils.c \ + ../../../src/util/safe-format-string.c \ + ../../../src/util/usertools.c \ ++ ../../../src/util/string_utils.c \ + ../../../src/util/strtonum.c \ + ../../../src/util/backup_file.c \ + ../../../src/util/atomic_io.c \ +diff --git a/src/util/string_utils.c b/src/util/string_utils.c +index a39b950e852de7ed43d6e8a32de3e7fb08a0dc56..71b2a092018076fd9c20ef9ac39a11964876cfc3 100644 +--- a/src/util/string_utils.c ++++ b/src/util/string_utils.c +@@ -83,3 +83,28 @@ char * sss_reverse_replace_space(TALLOC_CTX *mem_ctx, + + return replace_char(mem_ctx, orig_name, subst, ' '); + } ++ ++errno_t guid_blob_to_string_buf(const uint8_t *blob, char *str_buf, ++ size_t buf_size) ++{ ++ int ret; ++ ++ if (blob == NULL || str_buf == NULL || buf_size < GUID_STR_BUF_SIZE) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Buffer too small.\n"); ++ return EINVAL; ++ } ++ ++ ret = snprintf(str_buf, buf_size, ++ "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", ++ blob[3], blob[2], blob[1], blob[0], ++ blob[5], blob[4], ++ blob[7], blob[6], ++ blob[8], blob[9], ++ blob[10], blob[11],blob[12], blob[13],blob[14], blob[15]);; ++ if (ret != (GUID_STR_BUF_SIZE -1)) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "snprintf failed.\n"); ++ return EIO; ++ } ++ ++ return EOK; ++} +diff --git a/src/util/util.h b/src/util/util.h +index bf3a9a057aed77e93949370f8651af2631d91432..1530b550bb85c121cbc33c8c6353b7ecae9edaae 100644 +--- a/src/util/util.h ++++ b/src/util/util.h +@@ -618,6 +618,13 @@ char * sss_reverse_replace_space(TALLOC_CTX *mem_ctx, + const char *orig_name, + const char replace_char); + ++#define GUID_BIN_LENGTH 16 ++/* 16 2-digit hex values + 4 dashes + terminating 0 */ ++#define GUID_STR_BUF_SIZE (2 * GUID_BIN_LENGTH + 4 + 1) ++ ++errno_t guid_blob_to_string_buf(const uint8_t *blob, char *str_buf, ++ size_t buf_size); ++ + /* from become_user.c */ + errno_t become_user(uid_t uid, gid_t gid); + struct sss_creds; +-- +2.1.0 + diff --git a/SOURCES/0202-Download-complete-groups-if-ignore_group_members-is-.patch b/SOURCES/0202-Download-complete-groups-if-ignore_group_members-is-.patch new file mode 100644 index 0000000..59b00f7 --- /dev/null +++ b/SOURCES/0202-Download-complete-groups-if-ignore_group_members-is-.patch @@ -0,0 +1,76 @@ +From 591ee6dee11c4509e8e748ce83414913143e751d Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Fri, 22 May 2015 15:19:31 +0200 +Subject: [PATCH 202/207] Download complete groups if ignore_group_members is + set with tokengroups + +Resolves: + https://fedorahosted.org/sssd/ticket/2644 + +When tokenGroups are enabled, we save groups using their SID as the RDN +attribute during initgroups() and later, if the groups is requested and saved +again with the full name, remove the original and save the new group entry. + +Saving the new group entry would break if ignore_group_members is also +set, because the new group entry would lack the "member" attribute, so the +member/memberof links between the new group and the user entry wouldn't +be established again. + +This patch changes the initgroups processing so that the full group +object is fetched when initgroups is enabled but together with +ignore_group_members. This solution imposes some performance impact, +because instead of one search for tokenGroups we also need to resolve the +groups. The more systematic solution would be to get rid of removing the +group entry as described in https://fedorahosted.org/sssd/ticket/2656 + +To reproduce the bug, set: ignore_group_members = True with a +backend that uses: + id_provider = ad +Then run: + $ id aduser@ad_domain.com + $ id aduser@ad_domain.com + +Reviewed-by: Sumit Bose +(cherry picked from commit ee44aac95e42c3cb634876286a2aa4960ac69a2b) +--- + src/providers/ldap/sdap_async_initgroups_ad.c | 17 +++++++++++++++-- + 1 file changed, 15 insertions(+), 2 deletions(-) + +diff --git a/src/providers/ldap/sdap_async_initgroups_ad.c b/src/providers/ldap/sdap_async_initgroups_ad.c +index 9915f18..463d850 100644 +--- a/src/providers/ldap/sdap_async_initgroups_ad.c ++++ b/src/providers/ldap/sdap_async_initgroups_ad.c +@@ -1445,7 +1445,18 @@ sdap_ad_tokengroups_initgroups_send(TALLOC_CTX *mem_ctx, + state->use_id_mapping = use_id_mapping; + state->domain = domain; + +- if (state->use_id_mapping && !IS_SUBDOMAIN(state->domain)) { ++ /* We can compute the the gidNumber attribute from SIDs obtained from ++ * the tokenGroups lookup in case ID mapping is used for a user from the ++ * parent domain. For trusted domains, we need to know the group type ++ * to be able to filter out domain-local groups. Additionally, as a ++ * temporary workaround until https://fedorahosted.org/sssd/ticket/2656 ++ * is fixed, we also fetch the group object if group members are ignored ++ * to avoid having to transfer and retain members when the fake ++ * tokengroups object without name is replaced by the full group object ++ */ ++ if (state->use_id_mapping ++ && !IS_SUBDOMAIN(state->domain) ++ && state->domain->ignore_group_members == false) { + subreq = sdap_ad_tokengroups_initgr_mapping_send(state, ev, opts, + sysdb, domain, sh, + name, orig_dn, +@@ -1485,7 +1496,9 @@ static void sdap_ad_tokengroups_initgroups_done(struct tevent_req *subreq) + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct sdap_ad_tokengroups_initgroups_state); + +- if (state->use_id_mapping && !IS_SUBDOMAIN(state->domain)) { ++ if (state->use_id_mapping ++ && !IS_SUBDOMAIN(state->domain) ++ && state->domain->ignore_group_members == false) { + ret = sdap_ad_tokengroups_initgr_mapping_recv(subreq); + } else { + ret = sdap_ad_tokengroups_initgr_posix_recv(subreq); +-- +2.1.0 + diff --git a/SOURCES/0203-confdb-Add-new-option-subdomain_inherit.patch b/SOURCES/0203-confdb-Add-new-option-subdomain_inherit.patch new file mode 100644 index 0000000..8659f29 --- /dev/null +++ b/SOURCES/0203-confdb-Add-new-option-subdomain_inherit.patch @@ -0,0 +1,152 @@ +From a4dcc9a1290cfb82fde44bb8f4a4ab8d4668cd5b Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Wed, 29 Apr 2015 19:41:14 +0200 +Subject: [PATCH 203/207] confdb: Add new option subdomain_inherit + +Adds a new option subdomain_inherit that would allow administrators to pick +and choose which option to pass to subdomains. + +This option is required for: + https://fedorahosted.org/sssd/ticket/2644 +as a short-term fix. + +The proper solution is described in: + https://fedorahosted.org/sssd/ticket/2599 + +Reviewed-by: Pavel Reichl +(cherry picked from commit 1711cbfd2e36d44af1ae50e3a2beeec3a1f0b5e8) +--- + src/confdb/confdb.c | 13 +++++++++++++ + src/confdb/confdb.h | 2 ++ + src/config/SSSDConfig/__init__.py.in | 1 + + src/config/SSSDConfigTest.py | 6 ++++-- + src/config/etc/sssd.api.conf | 1 + + src/man/sssd.conf.5.xml | 20 +++++++++++++++++++- + 6 files changed, 40 insertions(+), 3 deletions(-) + +diff --git a/src/confdb/confdb.c b/src/confdb/confdb.c +index c55a945..6b2ce73 100644 +--- a/src/confdb/confdb.c ++++ b/src/confdb/confdb.c +@@ -1212,6 +1212,19 @@ static int confdb_get_domain_internal(struct confdb_ctx *cdb, + } + } + ++ tmp = ldb_msg_find_attr_as_string(res->msgs[0], ++ CONFDB_DOMAIN_SUBDOMAIN_INHERIT, ++ NULL); ++ if (tmp != NULL) { ++ ret = split_on_separator(domain, tmp, ',', true, true, ++ &domain->sd_inherit, NULL); ++ if (ret != 0) { ++ DEBUG(SSSDBG_FATAL_FAILURE, ++ "Cannot parse %s\n", CONFDB_SUBDOMAIN_ENUMERATE); ++ goto done; ++ } ++ } ++ + ret = get_entry_as_uint32(res->msgs[0], &domain->subdomain_refresh_interval, + CONFDB_DOMAIN_SUBDOMAIN_REFRESH, 14400); + if (ret != EOK || domain->subdomain_refresh_interval == 0) { +diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h +index 159aa9f..468c757 100644 +--- a/src/confdb/confdb.h ++++ b/src/confdb/confdb.h +@@ -183,6 +183,7 @@ + #define CONFDB_DOMAIN_PWD_EXPIRATION_WARNING "pwd_expiration_warning" + #define CONFDB_DOMAIN_REFRESH_EXPIRED_INTERVAL "refresh_expired_interval" + #define CONFDB_DOMAIN_OFFLINE_TIMEOUT "offline_timeout" ++#define CONFDB_DOMAIN_SUBDOMAIN_INHERIT "subdomain_inherit" + + /* Local Provider */ + #define CONFDB_LOCAL_DEFAULT_SHELL "default_shell" +@@ -263,6 +264,7 @@ struct sss_domain_info { + struct sss_domain_info *next; + + bool disabled; ++ char **sd_inherit; + }; + + /** +diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in +index 500bd71..8b9ab5a 100644 +--- a/src/config/SSSDConfig/__init__.py.in ++++ b/src/config/SSSDConfig/__init__.py.in +@@ -144,6 +144,7 @@ option_strings = { + 'dyndns_auth' : _("What kind of authentication should be used to perform the DNS update"), + 'subdomain_enumerate' : _('Control enumeration of trusted domains'), + 'subdomain_refresh_interval' : _('How often should subdomains list be refreshed'), ++ 'subdomain_inherit' : _('List of options that should be inherited into a subdomain'), + + # [provider/ipa] + 'ipa_domain' : _('IPA domain'), +diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py +index 78e22f6..6719132 100755 +--- a/src/config/SSSDConfigTest.py ++++ b/src/config/SSSDConfigTest.py +@@ -538,7 +538,8 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase): + 'hostid_provider', + 'subdomains_provider', + 'realmd_tags', +- 'subdomain_refresh_interval'] ++ 'subdomain_refresh_interval', ++ 'subdomain_inherit'] + + self.assertTrue(type(options) == dict, + "Options should be a dictionary") +@@ -897,7 +898,8 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase): + 'hostid_provider', + 'subdomains_provider', + 'realmd_tags', +- 'subdomain_refresh_interval'] ++ 'subdomain_refresh_interval', ++ 'subdomain_inherit'] + + self.assertTrue(type(options) == dict, + "Options should be a dictionary") +diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf +index c16769a..8b3dee6 100644 +--- a/src/config/etc/sssd.api.conf ++++ b/src/config/etc/sssd.api.conf +@@ -129,6 +129,7 @@ default_shell = str, None, false + description = str, None, false + realmd_tags = str, None, false + subdomain_refresh_interval = int, None, false ++subdomain_inherit = str, None, false + + #Entry cache timeouts + entry_cache_user_timeout = int, None, false +diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml +index 2002ccc..f7d688a 100644 +--- a/src/man/sssd.conf.5.xml ++++ b/src/man/sssd.conf.5.xml +@@ -476,7 +476,25 @@ + + + +- ++ ++ subdomain_inherit (string) ++ ++ ++ Specifies a list of configuration parameters that ++ should be inherited by a subdomain. Please note ++ that only selected parameters can be inherited. ++ ++ ++ Example: ++ ++subdomain_inherit = ldap_purge_cache_timeout ++ ++ ++ ++ Default: none ++ ++ ++ + + + +-- +2.1.0 + diff --git a/SOURCES/0204-DP-Add-a-function-to-inherit-DP-options-if-set.patch b/SOURCES/0204-DP-Add-a-function-to-inherit-DP-options-if-set.patch new file mode 100644 index 0000000..a2f16fe --- /dev/null +++ b/SOURCES/0204-DP-Add-a-function-to-inherit-DP-options-if-set.patch @@ -0,0 +1,308 @@ +From 092c9d35a4cc85c9910669bb3a8169f000ebc69c Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Wed, 6 May 2015 08:06:53 +0200 +Subject: [PATCH 204/207] DP: Add a function to inherit DP options, if set + +Related to: + https://fedorahosted.org/sssd/ticket/2644 + +Adds a utility function that checks if a DP option is present in +the subdomain_inherit list. If it is, then the option is set from source +to destination dp_option array. + +Reviewed-by: Pavel Reichl +(cherry picked from commit b3d110fbc424a03674a6e50e489a7cbab9702f0b) + +Conflicts: + src/tests/cmocka/test_dp_opts.c +--- + src/providers/data_provider.h | 5 ++ + src/providers/data_provider_opts.c | 57 +++++++++++++++++ + src/tests/cmocka/test_dp_opts.c | 127 ++++++++++++++++++++++++++++++++++--- + 3 files changed, 181 insertions(+), 8 deletions(-) + +diff --git a/src/providers/data_provider.h b/src/providers/data_provider.h +index 5df493e..657d2b7 100644 +--- a/src/providers/data_provider.h ++++ b/src/providers/data_provider.h +@@ -277,6 +277,11 @@ struct dp_option { + + #define DP_OPTION_TERMINATOR { NULL, 0, NULL_STRING, NULL_STRING } + ++void dp_option_inherit(char **inherit_opt_list, ++ int option, ++ struct dp_option *parent_opts, ++ struct dp_option *subdom_opts); ++ + int dp_get_options(TALLOC_CTX *memctx, + struct confdb_ctx *cdb, + const char *conf_path, +diff --git a/src/providers/data_provider_opts.c b/src/providers/data_provider_opts.c +index 8ad8456..9db43fc 100644 +--- a/src/providers/data_provider_opts.c ++++ b/src/providers/data_provider_opts.c +@@ -21,6 +21,63 @@ + + #include "data_provider.h" + ++/* =Copy-Option-From-Subdomain-If-Allowed================================= */ ++void dp_option_inherit(char **inherit_opt_list, ++ int option, ++ struct dp_option *parent_opts, ++ struct dp_option *subdom_opts) ++{ ++ errno_t ret; ++ bool inherit_option; ++ ++ inherit_option = string_in_list(parent_opts[option].opt_name, ++ inherit_opt_list, false); ++ if (inherit_option == false) { ++ DEBUG(SSSDBG_CONF_SETTINGS, ++ "Option %s is not set up to be inherited\n", ++ parent_opts[option].opt_name); ++ return; ++ } ++ ++ DEBUG(SSSDBG_CONF_SETTINGS, ++ "Will inherit option %s\n", parent_opts[option].opt_name); ++ switch (parent_opts[option].type) { ++ case DP_OPT_NUMBER: ++ ret = dp_opt_set_int(subdom_opts, ++ option, ++ dp_opt_get_int(parent_opts, ++ option)); ++ break; ++ case DP_OPT_STRING: ++ ret = dp_opt_set_string(subdom_opts, ++ option, ++ dp_opt_get_string(parent_opts, ++ option)); ++ break; ++ case DP_OPT_BLOB: ++ ret = dp_opt_set_blob(subdom_opts, ++ option, ++ dp_opt_get_blob(parent_opts, ++ option)); ++ break; ++ case DP_OPT_BOOL: ++ ret = dp_opt_set_bool(subdom_opts, ++ option, ++ dp_opt_get_bool(parent_opts, ++ option)); ++ break; ++ default: ++ ret = EINVAL; ++ break; ++ } ++ ++ if (ret != EOK) { ++ DEBUG(SSSDBG_MINOR_FAILURE, ++ "Failed to inherit option %s\n", parent_opts[option].opt_name); ++ /* Not fatal */ ++ } ++} ++ + /* =Retrieve-Options====================================================== */ + + int dp_get_options(TALLOC_CTX *memctx, +diff --git a/src/tests/cmocka/test_dp_opts.c b/src/tests/cmocka/test_dp_opts.c +index 0f3052a..60267ab 100644 +--- a/src/tests/cmocka/test_dp_opts.c ++++ b/src/tests/cmocka/test_dp_opts.c +@@ -284,37 +284,63 @@ void opt_test_getset_teardown(void **state) + talloc_free(opts); + } + +-void opt_test_getset_string(void **state) ++static void assert_nondefault_string_empty(struct dp_option *opts) + { +- struct dp_option *opts = talloc_get_type(*state, struct dp_option); +- int ret; + char *s; + + s = dp_opt_get_string(opts, OPT_STRING_NODEFAULT); + assert_null(s); ++} ++ ++static void set_nondefault_string(struct dp_option *opts) ++{ ++ int ret; + + ret = dp_opt_set_string(opts, OPT_STRING_NODEFAULT, "str1"); + assert_int_equal(ret, EOK); ++} ++ ++static void check_nondefault_string(struct dp_option *opts) ++{ ++ char *s; + + s = dp_opt_get_string(opts, OPT_STRING_NODEFAULT); + assert_non_null(s); + assert_string_equal(s, "str1"); + } + +-void opt_test_getset_blob(void **state) ++void opt_test_getset_string(void **state) + { + struct dp_option *opts = talloc_get_type(*state, struct dp_option); +- int ret; ++ ++ assert_nondefault_string_empty(opts); ++ set_nondefault_string(opts); ++ check_nondefault_string(opts); ++} ++ ++static void assert_nondefault_blob_empty(struct dp_option *opts) ++{ + struct dp_opt_blob b; + + b = dp_opt_get_blob(opts, OPT_BLOB_NODEFAULT); + assert_null(b.data); + assert_int_equal(b.length, 0); ++} ++ ++static void set_nondefault_blob(struct dp_option *opts) ++{ ++ struct dp_opt_blob b; ++ int ret; + + b.data = discard_const_p(uint8_t, "blob2"); + b.length = strlen("blob2"); + ret = dp_opt_set_blob(opts, OPT_BLOB_NODEFAULT, b); + assert_int_equal(ret, EOK); ++} ++ ++static void check_nondefault_blob(struct dp_option *opts) ++{ ++ struct dp_opt_blob b; + + b = dp_opt_get_blob(opts, OPT_BLOB_NODEFAULT); + assert_non_null(b.data); +@@ -322,22 +348,45 @@ void opt_test_getset_blob(void **state) + assert_memory_equal(b.data, "blob2", strlen("blob2")); + } + +-void opt_test_getset_int(void **state) ++void opt_test_getset_blob(void **state) + { + struct dp_option *opts = talloc_get_type(*state, struct dp_option); +- int ret; +- int i; + ++ assert_nondefault_blob_empty(opts); ++ set_nondefault_blob(opts); ++ check_nondefault_blob(opts); ++} ++ ++static void assert_nondefault_int_notset(struct dp_option *opts) ++{ ++ int i; + i = dp_opt_get_int(opts, OPT_INT_NODEFAULT); + assert_int_equal(i, 0); ++} + ++static void set_nondefault_int(struct dp_option *opts) ++{ ++ int ret; + ret = dp_opt_set_int(opts, OPT_INT_NODEFAULT, 456); + assert_int_equal(ret, EOK); ++} + ++static void assert_nondefault_int_set(struct dp_option *opts) ++{ ++ int i; + i = dp_opt_get_int(opts, OPT_INT_NODEFAULT); + assert_int_equal(i, 456); + } + ++void opt_test_getset_int(void **state) ++{ ++ struct dp_option *opts = talloc_get_type(*state, struct dp_option); ++ ++ assert_nondefault_int_notset(opts); ++ set_nondefault_int(opts); ++ assert_nondefault_int_set(opts); ++} ++ + void opt_test_getset_bool(void **state) + { + struct dp_option *opts = talloc_get_type(*state, struct dp_option); +@@ -354,6 +403,65 @@ void opt_test_getset_bool(void **state) + assert_false(b == true); + } + ++void opt_test_inherit(void **state) ++{ ++ struct dp_option *opts = talloc_get_type(*state, struct dp_option); ++ int ret; ++ struct dp_option *opts_copy; ++ const char *s; ++ const char *sd_inherit_match[] = { "string_nodefault", ++ "blob_nodefault", ++ "int_nodefault", ++ "bool_true", ++ NULL }; ++ ++ ret = dp_copy_defaults(opts, test_def_opts, ++ OPT_NUM_OPTS, &opts_copy); ++ assert_int_equal(ret, EOK); ++ assert_defaults(opts); ++ ++ dp_option_inherit(NULL, OPT_STRING_NODEFAULT, ++ opts, opts_copy); ++ s = dp_opt_get_string(opts_copy, OPT_STRING_NODEFAULT); ++ assert_null(s); ++ ++ /* string */ ++ assert_nondefault_string_empty(opts_copy); ++ set_nondefault_string(opts); ++ dp_option_inherit(discard_const(sd_inherit_match), ++ OPT_STRING_NODEFAULT, ++ opts, opts_copy); ++ check_nondefault_string(opts_copy); ++ ++ /* blob */ ++ assert_nondefault_blob_empty(opts_copy); ++ set_nondefault_blob(opts); ++ dp_option_inherit(discard_const(sd_inherit_match), ++ OPT_BLOB_NODEFAULT, ++ opts, opts_copy); ++ check_nondefault_blob(opts_copy); ++ ++ /* number */ ++ assert_nondefault_int_notset(opts_copy); ++ set_nondefault_int(opts); ++ dp_option_inherit(discard_const(sd_inherit_match), ++ OPT_INT_NODEFAULT, ++ opts, opts_copy); ++ assert_nondefault_int_set(opts_copy); ++ ++ /* bool */ ++ assert_true(dp_opt_get_bool(opts_copy, OPT_BOOL_TRUE)); ++ ++ ret = dp_opt_set_bool(opts, OPT_BOOL_TRUE, false); ++ assert_int_equal(ret, EOK); ++ ++ dp_option_inherit(discard_const(sd_inherit_match), ++ OPT_BOOL_TRUE, ++ opts, opts_copy); ++ ++ assert_false(dp_opt_get_bool(opts_copy, OPT_BOOL_TRUE)); ++} ++ + int main(int argc, const char *argv[]) + { + int no_cleanup = 0; +@@ -380,6 +488,9 @@ int main(int argc, const char *argv[]) + unit_test_setup_teardown(opt_test_getset_blob, + opt_test_getset_setup, + opt_test_getset_teardown), ++ unit_test_setup_teardown(opt_test_inherit, ++ opt_test_getset_setup, ++ opt_test_getset_teardown), + unit_test(opt_test_copy_default), + unit_test(opt_test_copy_options), + unit_test(opt_test_get) +-- +2.1.0 + diff --git a/SOURCES/0205-SDAP-Add-sdap_copy_map_entry.patch b/SOURCES/0205-SDAP-Add-sdap_copy_map_entry.patch new file mode 100644 index 0000000..f3f7307 --- /dev/null +++ b/SOURCES/0205-SDAP-Add-sdap_copy_map_entry.patch @@ -0,0 +1,162 @@ +From 62416ef0d547018872da915d0fe863780926d7be Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Fri, 22 May 2015 18:31:42 +0200 +Subject: [PATCH 205/207] SDAP: Add sdap_copy_map_entry + +Reviewed-by: Pavel Reichl +(cherry picked from commit 12089241f6a6eabf4f0c95669e5fc2bb3b503c06) + +Conflicts: + src/tests/cmocka/test_sdap.c +--- + src/providers/ldap/sdap.c | 17 +++++++++ + src/providers/ldap/sdap.h | 4 +++ + src/tests/cmocka/test_sdap.c | 82 ++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 103 insertions(+) + +diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c +index e428d5f..bc9f8b3 100644 +--- a/src/providers/ldap/sdap.c ++++ b/src/providers/ldap/sdap.c +@@ -28,6 +28,23 @@ + + /* =Retrieve-Options====================================================== */ + ++errno_t sdap_copy_map_entry(const struct sdap_attr_map *src_map, ++ struct sdap_attr_map *dst_map, ++ int entry_index) ++{ ++ if (src_map[entry_index].name != NULL) { ++ dst_map[entry_index].name = talloc_strdup(dst_map, ++ src_map[entry_index].name); ++ if (dst_map[entry_index].name == NULL) { ++ return ENOMEM; ++ } ++ } else { ++ dst_map->name = NULL; ++ } ++ ++ return EOK; ++} ++ + int sdap_copy_map(TALLOC_CTX *memctx, + struct sdap_attr_map *src_map, + int num_entries, +diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h +index 921051b..c0e9ff9 100644 +--- a/src/providers/ldap/sdap.h ++++ b/src/providers/ldap/sdap.h +@@ -467,6 +467,10 @@ struct sdap_deref_attrs { + struct sysdb_attrs *attrs; + }; + ++errno_t sdap_copy_map_entry(const struct sdap_attr_map *src_map, ++ struct sdap_attr_map *dst_map, ++ int entry_index); ++ + int sdap_copy_map(TALLOC_CTX *memctx, + struct sdap_attr_map *src_map, + int num_entries, +diff --git a/src/tests/cmocka/test_sdap.c b/src/tests/cmocka/test_sdap.c +index 404e100..d1e6959 100644 +--- a/src/tests/cmocka/test_sdap.c ++++ b/src/tests/cmocka/test_sdap.c +@@ -718,6 +718,80 @@ void test_parse_no_dn(void **state) + talloc_free(map); + } + ++struct copy_map_entry_test_ctx { ++ struct sdap_attr_map *src_map; ++ struct sdap_attr_map *dst_map; ++}; ++ ++static void copy_map_entry_test_setup(void **state) ++{ ++ int ret; ++ struct copy_map_entry_test_ctx *test_ctx; ++ ++ assert_true(leak_check_setup()); ++ ++ test_ctx = talloc_zero(global_talloc_context, ++ struct copy_map_entry_test_ctx); ++ assert_non_null(test_ctx); ++ ++ ret = sdap_copy_map(test_ctx, rfc2307_user_map, ++ SDAP_OPTS_USER, &test_ctx->src_map); ++ assert_int_equal(ret, ERR_OK); ++ ++ ret = sdap_copy_map(test_ctx, rfc2307_user_map, ++ SDAP_OPTS_USER, &test_ctx->dst_map); ++ assert_int_equal(ret, ERR_OK); ++ ++ check_leaks_push(test_ctx); ++ *state = test_ctx; ++} ++ ++static void copy_map_entry_test_teardown(void **state) ++{ ++ struct copy_map_entry_test_ctx *test_ctx = talloc_get_type_abort(*state, ++ struct copy_map_entry_test_ctx); ++ assert_true(check_leaks_pop(test_ctx) == true); ++ talloc_free(test_ctx); ++ assert_true(leak_check_teardown()); ++ return 0; ++} ++ ++static const char *copy_uuid(struct copy_map_entry_test_ctx *test_ctx) ++{ ++ errno_t ret; ++ ++ assert_null(test_ctx->dst_map[SDAP_AT_USER_UUID].name); ++ ret = sdap_copy_map_entry(test_ctx->src_map, test_ctx->dst_map, ++ SDAP_AT_USER_UUID); ++ assert_int_equal(ret, EOK); ++ return test_ctx->dst_map[SDAP_AT_USER_UUID].name; ++} ++ ++static void test_sdap_copy_map_entry(void **state) ++{ ++ struct copy_map_entry_test_ctx *test_ctx = talloc_get_type_abort(*state, ++ struct copy_map_entry_test_ctx); ++ const char *uuid_set_val = "test_uuid_val"; ++ const char *uuid_val = NULL; ++ ++ test_ctx->src_map[SDAP_AT_USER_UUID].name = discard_const(uuid_set_val); ++ ++ uuid_val = copy_uuid(test_ctx); ++ assert_non_null(uuid_val); ++ assert_string_equal(uuid_val, uuid_set_val); ++ talloc_free(test_ctx->dst_map[SDAP_AT_USER_UUID].name); ++} ++ ++static void test_sdap_copy_map_entry_null_name(void **state) ++{ ++ struct copy_map_entry_test_ctx *test_ctx = talloc_get_type_abort(*state, ++ struct copy_map_entry_test_ctx); ++ const char *uuid_val = NULL; ++ ++ uuid_val = copy_uuid(test_ctx); ++ assert_null(uuid_val); ++} ++ + int main(int argc, const char *argv[]) + { + poptContext pc; +@@ -763,6 +837,14 @@ int main(int argc, const char *argv[]) + unit_test_setup_teardown(test_parse_deref_map_mismatch, + parse_entry_test_setup, + parse_entry_test_teardown), ++ ++ /* Map option tests */ ++ unit_test_setup_teardown(test_sdap_copy_map_entry, ++ copy_map_entry_test_setup, ++ copy_map_entry_test_teardown), ++ unit_test_setup_teardown(test_sdap_copy_map_entry_null_name, ++ copy_map_entry_test_setup, ++ copy_map_entry_test_teardown), + }; + + /* Set debug level to invalid value so we can deside if -d 0 was used. */ +-- +2.1.0 + diff --git a/SOURCES/0206-UTIL-Inherit-ignore_group_members.patch b/SOURCES/0206-UTIL-Inherit-ignore_group_members.patch new file mode 100644 index 0000000..1e26b84 --- /dev/null +++ b/SOURCES/0206-UTIL-Inherit-ignore_group_members.patch @@ -0,0 +1,65 @@ +From 71565f0969738171e04f35e9aba93e63e4e83a8e Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Tue, 28 Apr 2015 17:04:51 +0200 +Subject: [PATCH 206/207] UTIL: Inherit ignore_group_members + +Resolves: + https://fedorahosted.org/sssd/ticket/2644 + +Allows the administrators to extend ignore_group_members to subdomains +as well by setting: + subdomain_inherit = ignore_group_members +in the domain section. + +Reviewed-by: Pavel Reichl +(cherry picked from commit 01c049ceef55c7bbfca1e47cecb2a0a2cf0a5d44) +--- + src/man/sssd.conf.5.xml | 4 ++++ + src/util/domain_info_utils.c | 9 +++++++++ + 2 files changed, 13 insertions(+) + +diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml +index f7d688a..19995be 100644 +--- a/src/man/sssd.conf.5.xml ++++ b/src/man/sssd.conf.5.xml +@@ -483,6 +483,10 @@ + Specifies a list of configuration parameters that + should be inherited by a subdomain. Please note + that only selected parameters can be inherited. ++ Currently the following options can be inherited: ++ ++ ++ ignore_group_members + + + Example: +diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c +index e0f1120..75eca8a 100644 +--- a/src/util/domain_info_utils.c ++++ b/src/util/domain_info_utils.c +@@ -206,6 +206,7 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx, + const char *forest) + { + struct sss_domain_info *dom; ++ bool inherit_option; + + DEBUG(SSSDBG_TRACE_FUNC, + "Creating [%s] as subdomain of [%s]!\n", name, parent->name); +@@ -281,6 +282,14 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx, + dom->enumerate = enumerate; + dom->fqnames = true; + dom->mpg = mpg; ++ /* If the parent domain filters out group members, the subdomain should ++ * as well if configured */ ++ inherit_option = string_in_list(CONFDB_DOMAIN_IGNORE_GROUP_MEMBERS, ++ parent->sd_inherit, false); ++ if (inherit_option) { ++ dom->ignore_group_members = parent->ignore_group_members; ++ } ++ + /* If the parent domain explicitly limits ID ranges, the subdomain + * should honour the limits as well. + */ +-- +2.1.0 + diff --git a/SOURCES/0207-subdomains-Inherit-cleanup-period-and-tokengroup-set.patch b/SOURCES/0207-subdomains-Inherit-cleanup-period-and-tokengroup-set.patch new file mode 100644 index 0000000..b888870 --- /dev/null +++ b/SOURCES/0207-subdomains-Inherit-cleanup-period-and-tokengroup-set.patch @@ -0,0 +1,340 @@ +From 8e382375715232130f7b96d3098a7c7a0d6cef7d Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Tue, 28 Apr 2015 13:48:42 +0200 +Subject: [PATCH 207/207] subdomains: Inherit cleanup period and tokengroup + settings from parent domain + +Allows the administrator to extend the functionality of +ldap_purge_cache_timeout, ldap_user_principal and ldap_use_tokengroups to +the subdomains. + +This is a less intrusive way of achieving: + https://fedorahosted.org/sssd/ticket/2627 + +Reviewed-by: Pavel Reichl +(cherry picked from commit 9b162bf39ef75629f54ffa1d0bd5f9c13119b650) + +Conflicts: + src/tests/cmocka/test_sdap.c +--- + src/man/sssd.conf.5.xml | 9 +++ + src/providers/ad/ad_subdomains.c | 4 + + src/providers/ipa/ipa_subdomains.c | 4 + + src/providers/ldap/sdap.c | 58 ++++++++++++++ + src/providers/ldap/sdap.h | 4 + + src/tests/cmocka/test_sdap.c | 158 +++++++++++++++++++++++++++++++++++++ + 6 files changed, 237 insertions(+) + +diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml +index 19995be..ef82dcd 100644 +--- a/src/man/sssd.conf.5.xml ++++ b/src/man/sssd.conf.5.xml +@@ -489,6 +489,15 @@ + ignore_group_members + + ++ ldap_purge_cache_timeout ++ ++ ++ ldap_use_tokengroups ++ ++ ++ ldap_user_principal ++ ++ + Example: + + subdomain_inherit = ldap_purge_cache_timeout +diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c +index 3c61d13..554da69 100644 +--- a/src/providers/ad/ad_subdomains.c ++++ b/src/providers/ad/ad_subdomains.c +@@ -180,6 +180,10 @@ ad_subdom_ad_ctx_new(struct be_ctx *be_ctx, + return EFAULT; + } + ++ sdap_inherit_options(subdom->parent->sd_inherit, ++ id_ctx->sdap_id_ctx->opts, ++ ad_id_ctx->sdap_id_ctx->opts); ++ + /* Set up the ID mapping object */ + ad_id_ctx->sdap_id_ctx->opts->idmap_ctx = + id_ctx->sdap_id_ctx->opts->idmap_ctx; +diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c +index 3148389..e529454 100644 +--- a/src/providers/ipa/ipa_subdomains.c ++++ b/src/providers/ipa/ipa_subdomains.c +@@ -228,6 +228,10 @@ ipa_ad_ctx_new(struct be_ctx *be_ctx, + return EFAULT; + } + ++ sdap_inherit_options(subdom->parent->sd_inherit, ++ id_ctx->sdap_id_ctx->opts, ++ ad_id_ctx->sdap_id_ctx->opts); ++ + ret = sdap_id_setup_tasks(be_ctx, + ad_id_ctx->sdap_id_ctx, + sdom, +diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c +index bc9f8b3..9b65940 100644 +--- a/src/providers/ldap/sdap.c ++++ b/src/providers/ldap/sdap.c +@@ -243,6 +243,64 @@ int sdap_extend_map_with_list(TALLOC_CTX *mem_ctx, + return EOK; + } + ++static void sdap_inherit_basic_options(char **inherit_opt_list, ++ struct dp_option *parent_opts, ++ struct dp_option *subdom_opts) ++{ ++ int inherit_options[] = { ++ SDAP_CACHE_PURGE_TIMEOUT, ++ SDAP_AD_USE_TOKENGROUPS, ++ SDAP_OPTS_BASIC /* sentinel */ ++ }; ++ int i; ++ ++ for (i = 0; inherit_options[i] != SDAP_OPTS_BASIC; i++) { ++ dp_option_inherit(inherit_opt_list, ++ inherit_options[i], ++ parent_opts, ++ subdom_opts); ++ } ++} ++ ++static void sdap_inherit_user_options(char **inherit_opt_list, ++ struct sdap_attr_map *parent_user_map, ++ struct sdap_attr_map *child_user_map) ++{ ++ int inherit_options[] = { ++ SDAP_AT_USER_PRINC, ++ SDAP_OPTS_USER /* sentinel */ ++ }; ++ int i; ++ int opt_index; ++ bool inherit_option; ++ ++ for (i = 0; inherit_options[i] != SDAP_OPTS_USER; i++) { ++ opt_index = inherit_options[i]; ++ ++ inherit_option = string_in_list(parent_user_map[opt_index].opt_name, ++ inherit_opt_list, ++ false); ++ if (inherit_option == false) { ++ continue; ++ } ++ ++ sdap_copy_map_entry(parent_user_map, child_user_map, opt_index); ++ } ++} ++ ++void sdap_inherit_options(char **inherit_opt_list, ++ struct sdap_options *parent_sdap_opts, ++ struct sdap_options *child_sdap_opts) ++{ ++ sdap_inherit_basic_options(inherit_opt_list, ++ parent_sdap_opts->basic, ++ child_sdap_opts->basic); ++ ++ sdap_inherit_user_options(inherit_opt_list, ++ parent_sdap_opts->user_map, ++ child_sdap_opts->user_map); ++} ++ + int sdap_get_map(TALLOC_CTX *memctx, + struct confdb_ctx *cdb, + const char *conf_path, +diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h +index c0e9ff9..19fc039 100644 +--- a/src/providers/ldap/sdap.h ++++ b/src/providers/ldap/sdap.h +@@ -491,6 +491,10 @@ int sdap_extend_map_with_list(TALLOC_CTX *mem_ctx, + struct sdap_attr_map **_map, + size_t *_new_size); + ++void sdap_inherit_options(char **inherit_opt_list, ++ struct sdap_options *parent_sdap_opts, ++ struct sdap_options *child_sdap_opts); ++ + int sdap_get_map(TALLOC_CTX *memctx, + struct confdb_ctx *cdb, + const char *conf_path, +diff --git a/src/tests/cmocka/test_sdap.c b/src/tests/cmocka/test_sdap.c +index d1e6959..5488694 100644 +--- a/src/tests/cmocka/test_sdap.c ++++ b/src/tests/cmocka/test_sdap.c +@@ -792,6 +792,150 @@ static void test_sdap_copy_map_entry_null_name(void **state) + assert_null(uuid_val); + } + ++struct test_sdap_inherit_ctx { ++ struct sdap_options *parent_sdap_opts; ++ struct sdap_options *child_sdap_opts; ++}; ++ ++struct sdap_options *mock_sdap_opts(TALLOC_CTX *mem_ctx) ++{ ++ int ret; ++ struct sdap_options *opts; ++ ++ opts = talloc_zero(mem_ctx, struct sdap_options); ++ assert_non_null(opts); ++ ++ ret = sdap_copy_map(opts, rfc2307_user_map, ++ SDAP_OPTS_USER, &opts->user_map); ++ assert_int_equal(ret, ERR_OK); ++ ++ ret = dp_copy_defaults(opts, default_basic_opts, ++ SDAP_OPTS_BASIC, &opts->basic); ++ assert_int_equal(ret, ERR_OK); ++ ++ return opts; ++} ++ ++static void test_sdap_inherit_option_setup(void **state) ++{ ++ int ret; ++ struct test_sdap_inherit_ctx *test_ctx; ++ ++ assert_true(leak_check_setup()); ++ ++ test_ctx = talloc_zero(global_talloc_context, ++ struct test_sdap_inherit_ctx); ++ assert_non_null(test_ctx); ++ ++ test_ctx->child_sdap_opts = talloc_zero(test_ctx, struct sdap_options); ++ ++ test_ctx->parent_sdap_opts = mock_sdap_opts(test_ctx); ++ assert_non_null(test_ctx->parent_sdap_opts); ++ test_ctx->child_sdap_opts = mock_sdap_opts(test_ctx); ++ assert_non_null(test_ctx->child_sdap_opts); ++ ++ test_ctx->parent_sdap_opts->user_map[SDAP_AT_USER_PRINC].name = \ ++ discard_const("test_princ"); ++ ++ ret = dp_opt_set_int(test_ctx->parent_sdap_opts->basic, ++ SDAP_CACHE_PURGE_TIMEOUT, 123); ++ assert_int_equal(ret, EOK); ++ ++ *state = test_ctx; ++} ++ ++static void test_sdap_inherit_option_teardown(void **state) ++{ ++ struct test_sdap_inherit_ctx *test_ctx = \ ++ talloc_get_type_abort(*state, struct test_sdap_inherit_ctx); ++ ++ talloc_free(test_ctx); ++ assert_true(leak_check_teardown()); ++} ++ ++static void test_sdap_inherit_option_null(void **state) ++{ ++ struct test_sdap_inherit_ctx *test_ctx = \ ++ talloc_get_type_abort(*state, struct test_sdap_inherit_ctx); ++ int val; ++ ++ val = dp_opt_get_int(test_ctx->child_sdap_opts->basic, ++ SDAP_CACHE_PURGE_TIMEOUT); ++ assert_int_equal(val, 10800); ++ ++ sdap_inherit_options(NULL, ++ test_ctx->parent_sdap_opts, ++ test_ctx->child_sdap_opts); ++ ++ val = dp_opt_get_int(test_ctx->child_sdap_opts->basic, ++ SDAP_CACHE_PURGE_TIMEOUT); ++ assert_int_equal(val, 10800); ++} ++ ++static void test_sdap_inherit_option_notset(void **state) ++{ ++ struct test_sdap_inherit_ctx *test_ctx = \ ++ talloc_get_type_abort(*state, struct test_sdap_inherit_ctx); ++ int val; ++ const char *inherit_options[] = { "ldap_use_tokengroups", NULL }; ++ ++ val = dp_opt_get_int(test_ctx->child_sdap_opts->basic, ++ SDAP_CACHE_PURGE_TIMEOUT); ++ assert_int_equal(val, 10800); ++ ++ /* parent has nondefault, but it's not supposed to be inherited */ ++ sdap_inherit_options(discard_const(inherit_options), ++ test_ctx->parent_sdap_opts, ++ test_ctx->child_sdap_opts); ++ ++ val = dp_opt_get_int(test_ctx->child_sdap_opts->basic, ++ SDAP_CACHE_PURGE_TIMEOUT); ++ assert_int_equal(val, 10800); ++} ++ ++static void test_sdap_inherit_option_basic(void **state) ++{ ++ struct test_sdap_inherit_ctx *test_ctx = \ ++ talloc_get_type_abort(*state, struct test_sdap_inherit_ctx); ++ int val; ++ const char *inherit_options[] = { "ldap_purge_cache_timeout", NULL }; ++ ++ val = dp_opt_get_int(test_ctx->child_sdap_opts->basic, ++ SDAP_CACHE_PURGE_TIMEOUT); ++ assert_int_equal(val, 10800); ++ ++ /* parent has nondefault, but it's not supposed to be inherited */ ++ sdap_inherit_options(discard_const(inherit_options), ++ test_ctx->parent_sdap_opts, ++ test_ctx->child_sdap_opts); ++ ++ val = dp_opt_get_int(test_ctx->child_sdap_opts->basic, ++ SDAP_CACHE_PURGE_TIMEOUT); ++ assert_int_equal(val, 123); ++} ++ ++static void test_sdap_inherit_option_user(void **state) ++{ ++ struct test_sdap_inherit_ctx *test_ctx = \ ++ talloc_get_type_abort(*state, struct test_sdap_inherit_ctx); ++ const char *inherit_options[] = { "ldap_user_principal", NULL }; ++ ++ assert_string_equal( ++ test_ctx->child_sdap_opts->user_map[SDAP_AT_USER_PRINC].name, ++ "krbPrincipalName"); ++ ++ /* parent has nondefault, but it's not supposed to be inherited */ ++ sdap_inherit_options(discard_const(inherit_options), ++ test_ctx->parent_sdap_opts, ++ test_ctx->child_sdap_opts); ++ ++ assert_string_equal( ++ test_ctx->child_sdap_opts->user_map[SDAP_AT_USER_PRINC].name, ++ "test_princ"); ++ ++ talloc_free(test_ctx->child_sdap_opts->user_map[SDAP_AT_USER_PRINC].name); ++} ++ + int main(int argc, const char *argv[]) + { + poptContext pc; +@@ -845,6 +989,20 @@ int main(int argc, const char *argv[]) + unit_test_setup_teardown(test_sdap_copy_map_entry_null_name, + copy_map_entry_test_setup, + copy_map_entry_test_teardown), ++ ++ /* Option inherit tests */ ++ unit_test_setup_teardown(test_sdap_inherit_option_null, ++ test_sdap_inherit_option_setup, ++ test_sdap_inherit_option_teardown), ++ unit_test_setup_teardown(test_sdap_inherit_option_notset, ++ test_sdap_inherit_option_setup, ++ test_sdap_inherit_option_teardown), ++ unit_test_setup_teardown(test_sdap_inherit_option_basic, ++ test_sdap_inherit_option_setup, ++ test_sdap_inherit_option_teardown), ++ unit_test_setup_teardown(test_sdap_inherit_option_user, ++ test_sdap_inherit_option_setup, ++ test_sdap_inherit_option_teardown), + }; + + /* Set debug level to invalid value so we can deside if -d 0 was used. */ +-- +2.1.0 + diff --git a/SOURCES/0208-sudo-sanitize-filter-values.patch b/SOURCES/0208-sudo-sanitize-filter-values.patch new file mode 100644 index 0000000..89e3f39 --- /dev/null +++ b/SOURCES/0208-sudo-sanitize-filter-values.patch @@ -0,0 +1,62 @@ +From ea10cbf8ec9669f4041c1df511b5f1b48aecce21 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Thu, 9 Apr 2015 13:03:08 +0200 +Subject: [PATCH 208/208] sudo: sanitize filter values + +Resolves: +https://fedorahosted.org/sssd/ticket/2613 + +Reviewed-by: Pavel Reichl +(cherry picked from commit c526cd124515cc2d44a413dcbfd4a74ddb490150) +(cherry picked from commit 2fb2a267d0d15cce84b0ccea7e088a4b580e42fb) +--- + src/db/sysdb_sudo.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +diff --git a/src/db/sysdb_sudo.c b/src/db/sysdb_sudo.c +index 261ed82d672cd95f0c0f429a177dae39d3b9c204..cd072dd2900757c69f7fd7f559559e310ceccda7 100644 +--- a/src/db/sysdb_sudo.c ++++ b/src/db/sysdb_sudo.c +@@ -221,6 +221,7 @@ sysdb_get_sudo_filter(TALLOC_CTX *mem_ctx, const char *username, + TALLOC_CTX *tmp_ctx = NULL; + char *filter = NULL; + char *specific_filter = NULL; ++ char *sanitized = NULL; + time_t now; + errno_t ret; + int i; +@@ -246,9 +247,14 @@ sysdb_get_sudo_filter(TALLOC_CTX *mem_ctx, const char *username, + } + + if ((flags & SYSDB_SUDO_FILTER_USERNAME) && (username != NULL)) { ++ ret = sss_filter_sanitize(tmp_ctx, username, &sanitized); ++ if (ret != EOK) { ++ goto done; ++ } ++ + specific_filter = talloc_asprintf_append(specific_filter, "(%s=%s)", + SYSDB_SUDO_CACHE_AT_USER, +- username); ++ sanitized); + NULL_CHECK(specific_filter, ret, done); + } + +@@ -261,9 +267,14 @@ sysdb_get_sudo_filter(TALLOC_CTX *mem_ctx, const char *username, + + if ((flags & SYSDB_SUDO_FILTER_GROUPS) && (groupnames != NULL)) { + for (i=0; groupnames[i] != NULL; i++) { ++ ret = sss_filter_sanitize(tmp_ctx, groupnames[i], &sanitized); ++ if (ret != EOK) { ++ goto done; ++ } ++ + specific_filter = talloc_asprintf_append(specific_filter, "(%s=%%%s)", + SYSDB_SUDO_CACHE_AT_USER, +- groupnames[i]); ++ sanitized); + NULL_CHECK(specific_filter, ret, done); + } + } +-- +2.4.3 + diff --git a/SPECS/sssd.spec b/SPECS/sssd.spec index 854a9be..aef7830 100644 --- a/SPECS/sssd.spec +++ b/SPECS/sssd.spec @@ -23,7 +23,7 @@ Name: sssd Version: 1.12.2 -Release: 58%{?dist}.6 +Release: 58%{?dist}.14 Group: Applications/System Summary: System Security Services Daemon License: GPLv3+ @@ -228,6 +228,18 @@ Patch0193: 0193-selinux-Handle-setup-with-empty-default-and-no-confi.patch Patch0194: 0194-IPA-idviews-check-if-view-name-is-set.patch Patch0195: 0195-IPA-make-sure-output-variable-is-set.patch Patch0196: 0196-IPA-set-EINVAL-if-dn-can-t-be-linearized.patch +Patch0197: 0197-LDAP-AD-do-not-resolve-group-members-during-tokenGro.patch +Patch0198: 0198-SDAP-Do-not-set-gid-0-twice.patch +Patch0199: 0199-SDAP-Extract-filtering-AD-group-to-function.patch +Patch0200: 0200-SDAP-Filter-ad-groups-in-initgroups.patch +Patch0201: 0201-sdap-properly-handle-binary-objectGuid-attribute.patch +Patch0202: 0202-Download-complete-groups-if-ignore_group_members-is-.patch +Patch0203: 0203-confdb-Add-new-option-subdomain_inherit.patch +Patch0204: 0204-DP-Add-a-function-to-inherit-DP-options-if-set.patch +Patch0205: 0205-SDAP-Add-sdap_copy_map_entry.patch +Patch0206: 0206-UTIL-Inherit-ignore_group_members.patch +Patch0207: 0207-subdomains-Inherit-cleanup-period-and-tokengroup-set.patch +Patch0208: 0208-sudo-sanitize-filter-values.patch ### Dependencies ### @@ -260,7 +272,7 @@ BuildRequires: libtevent-devel BuildRequires: libtdb-devel # LDB needs a strict version match to build -BuildRequires: libldb-devel = %{ldb_version} +BuildRequires: libldb-devel >= %{ldb_version} BuildRequires: libdhash-devel >= 0.4.2 BuildRequires: libcollection-devel BuildRequires: libini_config-devel >= 1.1.0-24 @@ -324,7 +336,7 @@ Conflicts: sssd < 1.10.0-8%{?dist}.beta2 # LDB needs a strict version match to run # This protects against # "sssd[XXX]: ldb: module version mismatch in src/ldb_modules/memberof.c" -Requires: libldb%{?_isa} = %{ldb_version} +Requires: libldb%{?_isa} >= %{ldb_version} Requires: libtdb%{?_isa} >= 1.1.3 Requires: sssd-client%{?_isa} = %{version}-%{release} @@ -642,7 +654,6 @@ autoreconf -ivf --with-krb5-rcache-dir=%{_localstatedir}/cache/krb5rcache \ --enable-nsslibdir=%{_libdir} \ --enable-pammoddir=%{_libdir}/security \ - --enable-ldb-version-check \ --enable-nfsidmaplibdir=%{_libdir}/libnfsidmap \ --disable-static \ --disable-rpath \ @@ -1093,6 +1104,29 @@ fi /usr/bin/rm -f /var/tmp/sssd.upgrade || : %changelog +* Mon Jul 20 2015 Jakub Hrozek - 1.12.2-58.14 +- Resolves: rhbz#1244761 - Relax the libldb requirements to unblock + RH Storage + +* Thu Jun 18 2015 Jakub Hrozek - 1.12.2-58.13 +- Resolves: rhbz#1232130 - sysdb sudo search doesn't escape special characters + +* Mon Jun 8 2015 Jakub Hrozek - 1.12.2-58.12 +- Resolves: rhbz#1226801 - ignore_group_members doesn't work for subdomains +- Resolves: rhbz#1226180 - Provide a way to disable the cleanup task + +* Thu May 28 2015 Jakub Hrozek - 1.12.2-58.9 +- Resolves: rhbz#1227772 - Properly handle AD's binary objectGUID + +* Wed Apr 22 2015 Jakub Hrozek - 1.12.2-58.8 +- Filter out domain-local groups during AD initgroups operation +- Related: rhbz#1214286 - SSSD downloads too much information when fetching + information about groups + +* Wed Apr 22 2015 Jakub Hrozek - 1.12.2-58.7 +- Resolves: rhbz#1214286 - SSSD downloads too much information when fetching + information about groups + * Thu Mar 19 2015 Jakub Hrozek - 1.12.2-58.6 - Initialize variable in the views code in one success and one failure path - Resolves: rhbz#1203365 - sssd_be segfault on IPA(when auth with AD