From e32d50862ea9df5680ce69987fc8154b7a8a628e Mon Sep 17 00:00:00 2001 From: Lukas Slebodnik Date: Thu, 25 Feb 2016 13:58:00 +0100 Subject: [PATCH] Resolves: rhbz#1310664 - [RFE] IPA: resolve external group memberships of IPA groups during getgrnam and getgrgid - Resolves: rhbz#1301303 - sss_obfuscate: SyntaxError: Missing parentheses in call to 'print' --- ...do-not-skip-cache-check-for-netgoups.patch | 108 +++ ...e_req-simplify-cache_req_cache_check.patch | 131 +++ ..._req-do-not-lookup-views-if-possible.patch | 146 +++ 0054-IDMAP-Fix-minor-memory-leak.patch | 54 ++ ...lace-obsoleted-macro-AC_PROG_LIBTOOL.patch | 30 + ...TS-Fix-race-condition-in-python-test.patch | 146 +++ ...s_obfuscate-should-work-with-python3.patch | 100 ++ ...HON-Fix-pep8-errors-in-sss_obfuscate.patch | 82 ++ ...nge-for-ldap_idmap_range_size-option.patch | 37 + 0060-NSS-Fix-memory-leak-netgroup.patch | 107 ++ ...-Add-test-to-validate-off-by-one-bug.patch | 189 ++++ ...P-Add-return-code-ERR_ACCOUNT_LOCKED.patch | 119 +++ ...t-lockout-status-and-display-message.patch | 198 ++++ ...pam_account_-expired-locked-_message.patch | 65 ++ ...ckport-error-code-ERR_ACCOUNT_LOCKED.patch | 45 + ...s_idmap-tests-Fix-segmentation-fault.patch | 51 + ...d-Warn-if-user-cannot-read-krb5.conf.patch | 74 ++ 0068-Fix-typos-reported-by-lintian.patch | 197 ++++ 0069-UTIL-Use-prefix-for-debug-function.patch | 97 ++ ...-Provide-varargs-version-of-debug_fn.patch | 97 ++ ...UTIL-Use-sss_vdebug_fn-for-callbacks.patch | 84 ++ ...venting-chown_debug_file-if-journald.patch | 75 ++ ...ENOENT-for-change-owner-of-log-files.patch | 35 + ...memory-leak-in-sss_colondb_writeline.patch | 39 + ...Fix-memory-leak-after-getline-failed.patch | 47 + ...Add-comments-on-functions-in-colondb.patch | 74 ++ ...S_COLONDB-Add-tests-for-sss_colondb_.patch | 504 ++++++++++ ...ew-option-ldap_group_external_member.patch | 178 ++++ ...e-to-call-into-IPA-provider-from-LDA.patch | 446 +++++++++ ...-provider-interface-to-resolve-exter.patch | 913 ++++++++++++++++++ ...-detect-endianness-at-configure-time.patch | 37 + sssd.spec | 39 +- 32 files changed, 4543 insertions(+), 1 deletion(-) create mode 100644 0051-NSS-do-not-skip-cache-check-for-netgoups.patch create mode 100644 0052-cache_req-simplify-cache_req_cache_check.patch create mode 100644 0053-cache_req-do-not-lookup-views-if-possible.patch create mode 100644 0054-IDMAP-Fix-minor-memory-leak.patch create mode 100644 0055-CONFIGURE-Replace-obsoleted-macro-AC_PROG_LIBTOOL.patch create mode 100644 0056-TESTS-Fix-race-condition-in-python-test.patch create mode 100644 0057-PYTHON-sss_obfuscate-should-work-with-python3.patch create mode 100644 0058-PYTHON-Fix-pep8-errors-in-sss_obfuscate.patch create mode 100644 0059-IDMAP-Man-change-for-ldap_idmap_range_size-option.patch create mode 100644 0060-NSS-Fix-memory-leak-netgroup.patch create mode 100644 0061-IDMAP-Add-test-to-validate-off-by-one-bug.patch create mode 100644 0062-SDAP-Add-return-code-ERR_ACCOUNT_LOCKED.patch create mode 100644 0063-PAM-Pass-account-lockout-status-and-display-message.patch create mode 100644 0064-PAM-Fix-man-for-pam_account_-expired-locked-_message.patch create mode 100644 0065-UTIL-Backport-error-code-ERR_ACCOUNT_LOCKED.patch create mode 100644 0066-sss_idmap-tests-Fix-segmentation-fault.patch create mode 100644 0067-krb5_child-Warn-if-user-cannot-read-krb5.conf.patch create mode 100644 0068-Fix-typos-reported-by-lintian.patch create mode 100644 0069-UTIL-Use-prefix-for-debug-function.patch create mode 100644 0070-UTIL-Provide-varargs-version-of-debug_fn.patch create mode 100644 0071-UTIL-Use-sss_vdebug_fn-for-callbacks.patch create mode 100644 0072-Revert-DEBUG-Preventing-chown_debug_file-if-journald.patch create mode 100644 0073-DEBUG-Ignore-ENOENT-for-change-owner-of-log-files.patch create mode 100644 0074-TOOLS-Fix-minor-memory-leak-in-sss_colondb_writeline.patch create mode 100644 0075-TOOLS-Fix-memory-leak-after-getline-failed.patch create mode 100644 0076-TOOLS-Add-comments-on-functions-in-colondb.patch create mode 100644 0077-TEST_TOOLS_COLONDB-Add-tests-for-sss_colondb_.patch create mode 100644 0078-Add-a-new-option-ldap_group_external_member.patch create mode 100644 0079-IPA-Add-interface-to-call-into-IPA-provider-from-LDA.patch create mode 100644 0080-LDAP-Use-the-IPA-provider-interface-to-resolve-exter.patch create mode 100644 0081-build-detect-endianness-at-configure-time.patch diff --git a/0051-NSS-do-not-skip-cache-check-for-netgoups.patch b/0051-NSS-do-not-skip-cache-check-for-netgoups.patch new file mode 100644 index 0000000..fbba01d --- /dev/null +++ b/0051-NSS-do-not-skip-cache-check-for-netgoups.patch @@ -0,0 +1,108 @@ +From 931a3a8fe35897552da09d6c0ca90b373538c094 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20=C5=BDidek?= +Date: Mon, 18 Jan 2016 22:02:55 +0100 +Subject: [PATCH 51/86] NSS: do not skip cache check for netgoups +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When refresh_expired_interval was not zero, +the NSS responder only refreshed netgroup cache +using background periodic task and ignored +SYSDB_CACHE_EXPIRE attribute. + +With this behaviour it was impossible to +get new netgroup from remote server even +after sss_cache tool was used to expire +existing entry in the cache. + +Resolves: +https://fedorahosted.org/sssd/ticket/2912 + +Reviewed-by: Pavel Březina +(cherry picked from commit 1b8858b1611db5048592f477059ca5ad66d7ceb1) +(cherry picked from commit 66c6bf86da1241c3253d23aa7e68850d6ec14d15) +--- + src/responder/nss/nsssrv_cmd.c | 47 +++++++++++++++++++++--------------------- + 1 file changed, 23 insertions(+), 24 deletions(-) + +diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c +index b8bd6425e2c937ce6008fd6663fe0312ad68f01e..c6f8284571be382dad5dfda651a25e4df6a14cb1 100644 +--- a/src/responder/nss/nsssrv_cmd.c ++++ b/src/responder/nss/nsssrv_cmd.c +@@ -579,10 +579,9 @@ static int nss_cmd_getpw_send_reply(struct nss_dom_ctx *dctx, bool filter) + return EOK; + } + +-/* Currently only refreshing expired netgroups is supported. */ + static bool + is_refreshed_on_bg(enum sss_dp_acct_type req_type, +- enum sss_dp_acct_type refresh_expired_interval) ++ uint32_t refresh_expired_interval) + { + if (refresh_expired_interval == 0) { + return false; +@@ -590,6 +589,8 @@ is_refreshed_on_bg(enum sss_dp_acct_type req_type, + + switch (req_type) { + case SSS_DP_NETGR: ++ case SSS_DP_USER: ++ case SSS_DP_GROUP: + return true; + default: + return false; +@@ -753,31 +754,29 @@ errno_t check_cache(struct nss_dom_ctx *dctx, + get_dp_name_and_id(dctx->cmdctx, dctx->domain, req_type, opt_name, opt_id, + &name, &id); + +- /* if we have any reply let's check cache validity, but ignore netgroups +- * if refresh_expired_interval is set (which implies that another method +- * is used to refresh netgroups) +- */ ++ /* if we have any reply let's check cache validity */ + if (res->count > 0) { +- if (is_refreshed_on_bg(req_type, +- dctx->domain->refresh_expired_interval)) { +- ret = EOK; ++ bool refreshed_on_bg; ++ uint32_t bg_refresh_interval = dctx->domain->refresh_expired_interval; ++ ++ if (req_type == SSS_DP_INITGROUPS) { ++ cacheExpire = ldb_msg_find_attr_as_uint64(res->msgs[0], ++ SYSDB_INITGR_EXPIRE, ++ 0); + } else { +- if (req_type == SSS_DP_INITGROUPS) { +- cacheExpire = ldb_msg_find_attr_as_uint64(res->msgs[0], +- SYSDB_INITGR_EXPIRE, +- 0); +- } else { +- cacheExpire = ldb_msg_find_attr_as_uint64(res->msgs[0], +- SYSDB_CACHE_EXPIRE, +- 0); +- } +- +- /* if we have any reply let's check cache validity */ +- ret = sss_cmd_check_cache(res->msgs[0], +- nctx->cache_refresh_percent, +- cacheExpire); ++ cacheExpire = ldb_msg_find_attr_as_uint64(res->msgs[0], ++ SYSDB_CACHE_EXPIRE, ++ 0); + } +- if (ret == EOK) { ++ ++ /* Check if background refresh is enabled for this entry */ ++ refreshed_on_bg = is_refreshed_on_bg(req_type, bg_refresh_interval); ++ ++ /* if we have any reply let's check cache validity */ ++ ret = sss_cmd_check_cache(res->msgs[0], ++ nctx->cache_refresh_percent, ++ cacheExpire); ++ if (ret == EOK || (ret == EAGAIN && refreshed_on_bg)) { + DEBUG(SSSDBG_TRACE_FUNC, "Cached entry is valid, returning..\n"); + return EOK; + } else if (ret != EAGAIN && ret != ENOENT) { +-- +2.5.0 + diff --git a/0052-cache_req-simplify-cache_req_cache_check.patch b/0052-cache_req-simplify-cache_req_cache_check.patch new file mode 100644 index 0000000..57bc1ec --- /dev/null +++ b/0052-cache_req-simplify-cache_req_cache_check.patch @@ -0,0 +1,131 @@ +From 4a3e2e2d6c6197cd40eec986f581e2a1abb9ef04 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Wed, 6 Jan 2016 12:08:18 +0100 +Subject: [PATCH 52/86] cache_req: simplify cache_req_cache_check() + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 46f34279204c537a53a0fac7e3fd8022359bfa09) +(cherry picked from commit 97e764f55211c209f2f97debe27f65d0185f4f50) +--- + src/responder/common/responder_cache_req.c | 79 ++++++++++++++++++------------ + 1 file changed, 48 insertions(+), 31 deletions(-) + +diff --git a/src/responder/common/responder_cache_req.c b/src/responder/common/responder_cache_req.c +index 4ab52b8188859f1143ba1ffa3de03d14ecc028c2..3a436d8e560c36f36553ca6b92204cc47d58dc2e 100644 +--- a/src/responder/common/responder_cache_req.c ++++ b/src/responder/common/responder_cache_req.c +@@ -568,6 +568,47 @@ static bool cache_req_bypass_cache(struct cache_req_input *input) + return false; + } + ++static errno_t cache_req_expiration_status(struct cache_req_input *input, ++ struct ldb_result *result, ++ time_t cache_refresh_percent) ++{ ++ time_t expire; ++ ++ if (result == NULL || result->count == 0 || cache_req_bypass_cache(input)) { ++ return ENOENT; ++ } ++ ++ if (input->type == CACHE_REQ_INITGROUPS) { ++ expire = ldb_msg_find_attr_as_uint64(result->msgs[0], ++ SYSDB_INITGR_EXPIRE, 0); ++ } else { ++ expire = ldb_msg_find_attr_as_uint64(result->msgs[0], ++ SYSDB_CACHE_EXPIRE, 0); ++ } ++ ++ return sss_cmd_check_cache(result->msgs[0], cache_refresh_percent, expire); ++} ++ ++static void cache_req_dpreq_params(struct cache_req_input *input, ++ const char **_string, ++ uint32_t *_id, ++ const char **_flag) ++{ ++ *_id = input->id; ++ *_string = input->dom_objname; ++ ++ if (input->type == CACHE_REQ_USER_BY_CERT) { ++ *_string = input->cert; ++ } ++ ++ *_flag = NULL; ++ if (DOM_HAS_VIEWS(input->domain)) { ++ *_flag = EXTRA_INPUT_MAYBE_WITH_VIEW; ++ } else if (cache_req_input_is_upn(input)) { ++ *_flag = EXTRA_NAME_IS_UPN; ++ } ++} ++ + struct cache_req_cache_state { + /* input data */ + struct tevent_context *ev; +@@ -669,38 +710,16 @@ static errno_t cache_req_cache_check(struct tevent_req *req) + struct cache_req_cache_state *state = NULL; + struct tevent_req *subreq = NULL; + const char *extra_flag = NULL; +- uint64_t cache_expire = 0; +- errno_t ret; + const char *search_str; ++ uint32_t search_id; ++ errno_t ret; + + state = tevent_req_data(req, struct cache_req_cache_state); + +- if (state->result == NULL || state->result->count == 0 || +- cache_req_bypass_cache(state->input) == true) { +- ret = ENOENT; +- } else { +- if (state->input->type == CACHE_REQ_INITGROUPS) { +- cache_expire = ldb_msg_find_attr_as_uint64(state->result->msgs[0], +- SYSDB_INITGR_EXPIRE, 0); +- } else { +- cache_expire = ldb_msg_find_attr_as_uint64(state->result->msgs[0], +- SYSDB_CACHE_EXPIRE, 0); +- } ++ cache_req_dpreq_params(state->input, &search_str, &search_id, &extra_flag); + +- ret = sss_cmd_check_cache(state->result->msgs[0], +- state->cache_refresh_percent, cache_expire); +- } +- +- search_str = state->input->dom_objname; +- if (state->input->type == CACHE_REQ_USER_BY_CERT) { +- search_str = state->input->cert; +- } +- +- if (DOM_HAS_VIEWS(state->input->domain)) { +- extra_flag = EXTRA_INPUT_MAYBE_WITH_VIEW; +- } else if (cache_req_input_is_upn(state->input)) { +- extra_flag = EXTRA_NAME_IS_UPN; +- } ++ ret = cache_req_expiration_status(state->input, state->result, ++ state->cache_refresh_percent); + + switch (ret) { + case EOK: +@@ -715,8 +734,7 @@ static errno_t cache_req_cache_check(struct tevent_req *req) + subreq = sss_dp_get_account_send(state, state->rctx, + state->input->domain, true, + state->input->dp_type, +- search_str, +- state->input->id, extra_flag); ++ search_str, search_id, extra_flag); + if (subreq == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory sending out-of-band " + "data provider request\n"); +@@ -733,8 +751,7 @@ static errno_t cache_req_cache_check(struct tevent_req *req) + subreq = sss_dp_get_account_send(state, state->rctx, + state->input->domain, true, + state->input->dp_type, +- search_str, +- state->input->id, extra_flag); ++ search_str, search_id, extra_flag); + if (subreq == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Out of memory sending data provider request\n"); +-- +2.5.0 + diff --git a/0053-cache_req-do-not-lookup-views-if-possible.patch b/0053-cache_req-do-not-lookup-views-if-possible.patch new file mode 100644 index 0000000..a3e2d08 --- /dev/null +++ b/0053-cache_req-do-not-lookup-views-if-possible.patch @@ -0,0 +1,146 @@ +From 6d3c0f1d269193c366945dcdaeff45dd139230cb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Wed, 6 Jan 2016 12:45:38 +0100 +Subject: [PATCH 53/86] cache_req: do not lookup views if possible + +This is needed for LOCAL view but also creates a shortcut for +server side overrides. + +Resolves: +https://fedorahosted.org/sssd/ticket/2849 + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 5f2b1986a16a394ecbecd16f82c7265b5b47b546) +(cherry picked from commit f840cfd6c2ad61045160f301d6ae7276e3e33f54) +--- + src/responder/common/responder_cache_req.c | 98 +++++++++++++++++++++++++++--- + 1 file changed, 88 insertions(+), 10 deletions(-) + +diff --git a/src/responder/common/responder_cache_req.c b/src/responder/common/responder_cache_req.c +index 3a436d8e560c36f36553ca6b92204cc47d58dc2e..2344b0f09c6c4242ff3f769ae565f21c1d2b3e3b 100644 +--- a/src/responder/common/responder_cache_req.c ++++ b/src/responder/common/responder_cache_req.c +@@ -589,24 +589,101 @@ static errno_t cache_req_expiration_status(struct cache_req_input *input, + return sss_cmd_check_cache(result->msgs[0], cache_refresh_percent, expire); + } + +-static void cache_req_dpreq_params(struct cache_req_input *input, ++static void cache_req_dpreq_params(TALLOC_CTX *mem_ctx, ++ struct cache_req_input *input, ++ struct ldb_result *result, + const char **_string, + uint32_t *_id, + const char **_flag) + { ++ struct ldb_result *user = NULL; ++ const char *name = NULL; ++ uint32_t id = 0; ++ errno_t ret; ++ + *_id = input->id; + *_string = input->dom_objname; +- +- if (input->type == CACHE_REQ_USER_BY_CERT) { +- *_string = input->cert; +- } +- + *_flag = NULL; +- if (DOM_HAS_VIEWS(input->domain)) { +- *_flag = EXTRA_INPUT_MAYBE_WITH_VIEW; +- } else if (cache_req_input_is_upn(input)) { ++ ++ if (cache_req_input_is_upn(input)) { + *_flag = EXTRA_NAME_IS_UPN; ++ return; + } ++ ++ if (input->type == CACHE_REQ_USER_BY_CERT) { ++ *_string = input->cert; ++ return; ++ } ++ ++ if (!DOM_HAS_VIEWS(input->domain)) { ++ return; ++ } ++ ++ /* We must search with views. */ ++ if (result == NULL || result->count == 0) { ++ *_flag = EXTRA_INPUT_MAYBE_WITH_VIEW; ++ return; ++ } ++ ++ /* If domain has views we will try to user original values instead of the ++ * overridden ones. This is a must for the LOCAL view since we can't look ++ * it up otherwise. But it is also a shortcut for non-local views where ++ * we will not fail over to the overridden value. */ ++ ++ switch (input->type) { ++ case CACHE_REQ_USER_BY_NAME: ++ case CACHE_REQ_GROUP_BY_NAME: ++ name = ldb_msg_find_attr_as_string(result->msgs[0], SYSDB_NAME, NULL); ++ if (name == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: name cannot be NULL\n"); ++ } ++ break; ++ case CACHE_REQ_USER_BY_ID: ++ id = ldb_msg_find_attr_as_uint64(result->msgs[0], SYSDB_UIDNUM, 0); ++ if (id == 0) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: id cannot be 0\n"); ++ } ++ break; ++ case CACHE_REQ_GROUP_BY_ID: ++ id = ldb_msg_find_attr_as_uint64(result->msgs[0], SYSDB_GIDNUM, 0); ++ if (id == 0) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: id cannot be 0\n"); ++ } ++ break; ++ case CACHE_REQ_INITGROUPS: ++ ret = sysdb_getpwnam_with_views(NULL, input->domain, ++ input->dom_objname, &user); ++ if (ret != EOK || user == NULL || user->count != 1) { ++ /* Case where the user is not found has been already handled. If ++ * this is not OK, it is an error. */ ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to match initgroups user " ++ "[%d]: %s\n", ret, sss_strerror(ret)); ++ break; ++ } ++ ++ name = ldb_msg_find_attr_as_string(user->msgs[0], SYSDB_NAME, ++ NULL); ++ if (name == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Bug: name cannot be NULL\n"); ++ break; ++ } ++ ++ talloc_steal(mem_ctx, name); ++ talloc_free(user); ++ break; ++ default: ++ return; ++ } ++ ++ /* Now we have the original name and id. We don't have to search with ++ * views unless some error occurred. */ ++ if (name == NULL && id == 0) { ++ *_flag = EXTRA_INPUT_MAYBE_WITH_VIEW; ++ return; ++ } ++ ++ *_string = talloc_steal(mem_ctx, name); ++ *_id = id; + } + + struct cache_req_cache_state { +@@ -716,7 +793,8 @@ static errno_t cache_req_cache_check(struct tevent_req *req) + + state = tevent_req_data(req, struct cache_req_cache_state); + +- cache_req_dpreq_params(state->input, &search_str, &search_id, &extra_flag); ++ cache_req_dpreq_params(state, state->input, state->result, ++ &search_str, &search_id, &extra_flag); + + ret = cache_req_expiration_status(state->input, state->result, + state->cache_refresh_percent); +-- +2.5.0 + diff --git a/0054-IDMAP-Fix-minor-memory-leak.patch b/0054-IDMAP-Fix-minor-memory-leak.patch new file mode 100644 index 0000000..5f41932 --- /dev/null +++ b/0054-IDMAP-Fix-minor-memory-leak.patch @@ -0,0 +1,54 @@ +From 521ef4f7839216e19ad93420f0464ba969fead8b Mon Sep 17 00:00:00 2001 +From: Pavel Reichl +Date: Fri, 22 Jan 2016 12:30:23 -0500 +Subject: [PATCH 54/86] IDMAP: Fix minor memory leak +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Reviewed-by: Michal Židek +(cherry picked from commit 5554a2a679f72f19f266d660a5681e3b0c657379) +(cherry picked from commit fe8d58c75da2b9b3704bb2ae19f8014323797757) +--- + src/lib/idmap/sss_idmap.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +diff --git a/src/lib/idmap/sss_idmap.c b/src/lib/idmap/sss_idmap.c +index 269ef0132ff3b9ffbfbe65006361fac6d4f88cf9..e3e9972b802748770a5f7440fa8ddc8ba75d3362 100644 +--- a/src/lib/idmap/sss_idmap.c ++++ b/src/lib/idmap/sss_idmap.c +@@ -607,13 +607,13 @@ get_helpers(struct sss_idmap_ctx *ctx, + for (int i = 0; i < ctx->idmap_opts.extra_slice_init; i++) { + secondary_name = generate_sec_slice_name(ctx, domain_sid, first_rid); + if (secondary_name == NULL) { +- return IDMAP_OUT_OF_MEMORY; ++ err = IDMAP_OUT_OF_MEMORY; ++ goto fail; + } + + err = generate_slice(ctx, secondary_name, first_rid, &slice); + if (err != IDMAP_SUCCESS) { +- ctx->free_func(secondary_name, ctx->alloc_pvt); +- return err; ++ goto fail; + } + + first_rid += ctx->idmap_opts.rangesize; +@@ -631,6 +631,14 @@ get_helpers(struct sss_idmap_ctx *ctx, + + *_sec_slices = sec_slices; + return IDMAP_SUCCESS; ++ ++fail: ++ ctx->free_func(secondary_name, ctx->alloc_pvt); ++ ++ /* Free already generated helpers. */ ++ free_helpers(ctx, sec_slices, true); ++ ++ return err; + } + + enum idmap_error_code sss_idmap_add_domain_ex(struct sss_idmap_ctx *ctx, +-- +2.5.0 + diff --git a/0055-CONFIGURE-Replace-obsoleted-macro-AC_PROG_LIBTOOL.patch b/0055-CONFIGURE-Replace-obsoleted-macro-AC_PROG_LIBTOOL.patch new file mode 100644 index 0000000..dba990b --- /dev/null +++ b/0055-CONFIGURE-Replace-obsoleted-macro-AC_PROG_LIBTOOL.patch @@ -0,0 +1,30 @@ +From 92281a16d6e8988dec661fe40eac6361b7bcfb4a Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Mon, 1 Feb 2016 09:34:08 +0100 +Subject: [PATCH 55/86] CONFIGURE: Replace obsoleted macro AC_PROG_LIBTOOL + +The AC_PROG_LIBTOOL macro is obsoleted since libtool 2.0 + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 700d45751e997c634504a4f22facd2edf82edea7) +(cherry picked from commit dba300fe84fe40919a17a82bc4f4b9b672ed195d) +--- + configure.ac | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index 1ab64765968e9ffe94da9075496be2491bf33e9a..8ef2493c79a144d348200213f0ce1681d0fa3c1f 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -19,7 +19,7 @@ AM_PROG_CC_C_O + m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) + AC_DISABLE_STATIC + AC_PROG_INSTALL +-AC_PROG_LIBTOOL ++LT_INIT + m4_ifdef([AC_PROG_MKDIR_P], + [AC_PROG_MKDIR_P], + [AC_SUBST([MKDIR_P], "mkdir -p")]) +-- +2.5.0 + diff --git a/0056-TESTS-Fix-race-condition-in-python-test.patch b/0056-TESTS-Fix-race-condition-in-python-test.patch new file mode 100644 index 0000000..cf29aea --- /dev/null +++ b/0056-TESTS-Fix-race-condition-in-python-test.patch @@ -0,0 +1,146 @@ +From c53781ec735a14c346fa111749ac02030e550fb5 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Wed, 13 Jan 2016 15:06:06 +0100 +Subject: [PATCH 56/86] TESTS: Fix race condition in python test + +Python tests for pyhbac and pysss_murmur created symbolic +links in shared directory ".libs". It happened that both +tests created symbolic link in the same time and therefore +python2 test could try to import link to python3 module +which caused failures in tests. + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 9e1de5c83371d91e200254cceef70852f5f94fd2) +(cherry picked from commit 94bafaad2401bc647a31a22953ad2d985c88b06e) +--- + src/tests/pyhbac-test.py | 33 ++++++++++++++++----------------- + src/tests/pysss_murmur-test.py | 33 ++++++++++++++++----------------- + 2 files changed, 32 insertions(+), 34 deletions(-) + +diff --git a/src/tests/pyhbac-test.py b/src/tests/pyhbac-test.py +index 9d8fd1a333bf54ecf21d14d3b6293f7294a0d53e..09867311ed42cad1e3b44e10616edb084716ce10 100755 +--- a/src/tests/pyhbac-test.py ++++ b/src/tests/pyhbac-test.py +@@ -5,11 +5,12 @@ import unittest + import sys + import os + import copy +-import sys +-import errno ++import tempfile ++ ++BUILD_DIR = os.getenv('builddir') or "." ++TEST_DIR = os.getenv('SSS_TEST_DIR') or "." ++MODPATH = tempfile.mkdtemp(prefix="tp_pyhbac_", dir=TEST_DIR) + +-srcdir = os.getenv('builddir') or "." +-MODPATH = srcdir + "/.libs" #FIXME - is there a way to get this from libtool? + + if sys.version_info[0] > 2: + unicode = str +@@ -40,22 +41,15 @@ class PyHbacImport(unittest.TestCase): + def testImport(self): + " Import the module and assert it comes from tree " + try: +- cwd_backup = os.getcwd() ++ dest_module_path = MODPATH + "/pyhbac.so" + +- try: +- os.unlink(MODPATH + "/pyhbac.so") +- except OSError as e: +- if e.errno == errno.ENOENT: +- pass +- else: +- raise e +- +- os.chdir(MODPATH) + if sys.version_info[0] > 2: +- os.symlink("_py3hbac.so", "pyhbac.so") ++ src_module_path = BUILD_DIR + "/.libs/_py3hbac.so" + else: +- os.symlink("_py2hbac.so", "pyhbac.so") +- os.chdir(cwd_backup) ++ src_module_path = BUILD_DIR + "/.libs/_py2hbac.so" ++ ++ src_module_path = os.path.abspath(src_module_path) ++ os.symlink(src_module_path, dest_module_path) + + import pyhbac + except ImportError as e: +@@ -456,6 +450,11 @@ class PyHbacRequestTest(unittest.TestCase): + self.assertRaises(TypeError, req.evaluate, (allow_rule, None)) + + class PyHbacModuleTest(unittest.TestCase): ++ @classmethod ++ def tearDownClass(cls): ++ os.unlink(MODPATH + "/pyhbac.so") ++ os.rmdir(MODPATH) ++ + def testHasResultTypes(self): + assert hasattr(pyhbac, "HBAC_EVAL_ALLOW") + assert hasattr(pyhbac, "HBAC_EVAL_DENY") +diff --git a/src/tests/pysss_murmur-test.py b/src/tests/pysss_murmur-test.py +index faa8bb2d33b9d94d380b8f7045ba45aa06ac4793..1cbbe4d03172804ef16b630d3dd1c3a22e09a20a 100755 +--- a/src/tests/pysss_murmur-test.py ++++ b/src/tests/pysss_murmur-test.py +@@ -22,11 +22,12 @@ from __future__ import print_function + import unittest + import sys + import os +-import copy +-import errno ++import tempfile ++ ++BUILD_DIR = os.getenv('builddir') or "." ++TEST_DIR = os.getenv('SSS_TEST_DIR') or "." ++MODPATH = tempfile.mkdtemp(prefix="tp_pysss_murmur_", dir=TEST_DIR) + +-srcdir = os.getenv('builddir') or "." +-MODPATH = srcdir + "/.libs" #FIXME - is there a way to get this from libtool? + + def compat_assertItemsEqual(this, expected_seq, actual_seq, msg=None): + return this.assertEqual(sorted(expected_seq), sorted(actual_seq)) +@@ -56,22 +57,15 @@ class PySssMurmurImport(unittest.TestCase): + def testImport(self): + " Import the module and assert it comes from tree " + try: +- cwd_backup = os.getcwd() ++ dest_module_path = MODPATH + "/pysss_murmur.so" + +- try: +- os.unlink(MODPATH + "/pysss_murmur.so") +- except OSError as e: +- if e.errno == errno.ENOENT: +- pass +- else: +- raise e +- +- os.chdir(MODPATH) + if sys.version_info[0] > 2: +- os.symlink("_py3sss_murmur.so", "pysss_murmur.so") ++ src_module_path = BUILD_DIR + "/.libs/_py3sss_murmur.so" + else: +- os.symlink("_py2sss_murmur.so", "pysss_murmur.so") +- os.chdir(cwd_backup) ++ src_module_path = BUILD_DIR + "/.libs/_py2sss_murmur.so" ++ ++ src_module_path = os.path.abspath(src_module_path) ++ os.symlink(src_module_path, dest_module_path) + + import pysss_murmur + except ImportError as e: +@@ -80,6 +74,11 @@ class PySssMurmurImport(unittest.TestCase): + self.assertEqual(pysss_murmur.__file__, MODPATH + "/pysss_murmur.so") + + class PySssMurmurTest(unittest.TestCase): ++ @classmethod ++ def tearDownClass(cls): ++ os.unlink(MODPATH + "/pysss_murmur.so") ++ os.rmdir(MODPATH) ++ + def testExpectedHash(self): + hash = pysss_murmur.murmurhash3("S-1-5-21-2153326666-2176343378-3404031434", 41, 0xdeadbeef) + self.assertEqual(hash, 93103853) +-- +2.5.0 + diff --git a/0057-PYTHON-sss_obfuscate-should-work-with-python3.patch b/0057-PYTHON-sss_obfuscate-should-work-with-python3.patch new file mode 100644 index 0000000..18a6870 --- /dev/null +++ b/0057-PYTHON-sss_obfuscate-should-work-with-python3.patch @@ -0,0 +1,100 @@ +From 8fc61f5bba2f8c06b0d86d177f2e11d5c7f5d874 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Wed, 27 Jan 2016 16:02:33 +0100 +Subject: [PATCH 57/86] PYTHON: sss_obfuscate should work with python3 + +Based on patch from: Steven W. Elling + +Resolves: +https://fedorahosted.org/sssd/ticket/2937 + +Reviewed-by: Martin Basti +(cherry picked from commit 11496692da75a330de01d5f15b7183d2439efd3c) +(cherry picked from commit 683b9d012117016483b99620c333be666a6c888e) +--- + src/tools/sss_obfuscate | 24 +++++++++++++----------- + 1 file changed, 13 insertions(+), 11 deletions(-) + +diff --git a/src/tools/sss_obfuscate b/src/tools/sss_obfuscate +index fbea1213d8f7e99ab3b1a6d7d24accf8a6194094..68ef30e386ced95b85afbea87696e3c69bea7b51 100644 +--- a/src/tools/sss_obfuscate ++++ b/src/tools/sss_obfuscate +@@ -1,5 +1,7 @@ + #!/usr/bin/python + ++from __future__ import print_function ++ + import sys + from optparse import OptionParser + +@@ -33,11 +35,11 @@ def parse_options(): + def main(): + options, args = parse_options() + if not options: +- print >> sys.stderr, "Cannot parse options" ++ print("Cannot parse options", file=sys.stderr) + return 1 + + if not options.domain: +- print >> sys.stderr, "No domain specified" ++ print("No domain specified", file=sys.stderr) + return 1 + + if not options.stdin: +@@ -59,7 +61,8 @@ def main(): + password = p1 + + except EOFError: +- print >> sys.stderr, '\nUnexpected end-of-file. Password change aborted' ++ print('\nUnexpected end-of-file. Password change aborted', ++ file=sys.stderr) + return 1 + except KeyboardInterrupt: + return 1 +@@ -78,26 +81,26 @@ def main(): + try: + sssdconfig = SSSDConfig.SSSDConfig() + except IOError: +- print "Cannot read internal configuration files." ++ print("Cannot read internal configuration files.") + return 1 + try: + sssdconfig.import_config(options.filename) + except IOError: +- print "Permissions error reading config file" ++ print("Permissions error reading config file") + return 1 + + try: + domain = sssdconfig.get_domain(options.domain) + except SSSDConfig.NoDomainError: +- print "No such domain %s" % options.domain ++ print("No such domain %s" % options.domain) + return 1 + + try: + domain.set_option('ldap_default_authtok_type', 'obfuscated_password') + domain.set_option('ldap_default_authtok', obfpwd) + except SSSDConfig.NoOptionError: +- print "The domain %s does not seem to support the required options" % \ +- options.domain ++ print("The domain %s does not seem to support the required options" ++ % options.domain) + return 1 + + +@@ -106,9 +109,8 @@ def main(): + sssdconfig.write() + except IOError: + # File could not be written +- print >> sys.stderr, "Could not write to config file. Check that " \ +- "you have the appropriate permissions to edit " \ +- "this file." ++ print("Could not write to config file. Check that you have the " ++ "appropriate permissions to edit this file.", file=sys.stderr) + return 1 + + return 0 +-- +2.5.0 + diff --git a/0058-PYTHON-Fix-pep8-errors-in-sss_obfuscate.patch b/0058-PYTHON-Fix-pep8-errors-in-sss_obfuscate.patch new file mode 100644 index 0000000..050c183 --- /dev/null +++ b/0058-PYTHON-Fix-pep8-errors-in-sss_obfuscate.patch @@ -0,0 +1,82 @@ +From 1d7742a2b98c1494af2ce1c3eb3d6850ea1e78e9 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Wed, 27 Jan 2016 17:49:45 +0100 +Subject: [PATCH 58/86] PYTHON: Fix pep8 errors in sss_obfuscate + +src/tools/sss_obfuscate:12:1: E302 expected 2 blank lines, found 1 +src/tools/sss_obfuscate:29:80: E501 line too long (111 > 79 characters) +src/tools/sss_obfuscate:35:1: E302 expected 2 blank lines, found 1 +src/tools/sss_obfuscate:47:80: E501 line too long (107 > 79 characters) +src/tools/sss_obfuscate:50:13: E265 block comment should start with '# ' +src/tools/sss_obfuscate:58:17: E265 block comment should start with '# ' +src/tools/sss_obfuscate:107:5: E303 too many blank lines (2) + +Reviewed-by: Martin Basti +(cherry picked from commit 37ea8e70fa13ff9ba563300fb15de0e5e6185d68) +(cherry picked from commit f61eb0c92251dbe65a2868aa1ded470d1f2739c8) +--- + src/tools/sss_obfuscate | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +diff --git a/src/tools/sss_obfuscate b/src/tools/sss_obfuscate +index 68ef30e386ced95b85afbea87696e3c69bea7b51..5981e81410af68fd8123781a5e21a0c7fa3bcb23 100644 +--- a/src/tools/sss_obfuscate ++++ b/src/tools/sss_obfuscate +@@ -9,6 +9,7 @@ import pysss + import SSSDConfig + import getpass + ++ + def parse_options(): + parser = OptionParser() + parser.set_description("sss_obfuscate converts a given password into \ +@@ -26,12 +27,14 @@ def parse_options(): + metavar="DOMNAME") + parser.add_option("-f", "--file", + dest="filename", default=None, +- help="Set input file to FILE (default: Use system default, usually /etc/sssd/sssd.conf)", ++ help="Set input file to FILE (default: Use system " ++ "default, usually /etc/sssd/sssd.conf)", + metavar="FILE") + (options, args) = parser.parse_args() + + return options, args + ++ + def main(): + options, args = parse_options() + if not options: +@@ -44,10 +47,11 @@ def main(): + + if not options.stdin: + try: +- pprompt = lambda: (getpass.getpass("Enter password: "), getpass.getpass("Re-enter password: ")) ++ pprompt = lambda: (getpass.getpass("Enter password: "), ++ getpass.getpass("Re-enter password: ")) + p1, p2 = pprompt() + +- #Work around bug in Python 2.6 ++ # Work around bug in Python 2.6 + if '\x03' in p1 or '\x03' in p2: + raise KeyboardInterrupt + +@@ -55,7 +59,7 @@ def main(): + print('Passwords do not match. Try again') + p1, p2 = pprompt() + +- #Work around bug in Python 2.6 ++ # Work around bug in Python 2.6 + if '\x03' in p1 or '\x03' in p2: + raise KeyboardInterrupt + password = p1 +@@ -103,7 +107,6 @@ def main(): + % options.domain) + return 1 + +- + sssdconfig.save_domain(domain) + try: + sssdconfig.write() +-- +2.5.0 + diff --git a/0059-IDMAP-Man-change-for-ldap_idmap_range_size-option.patch b/0059-IDMAP-Man-change-for-ldap_idmap_range_size-option.patch new file mode 100644 index 0000000..7fe84ad --- /dev/null +++ b/0059-IDMAP-Man-change-for-ldap_idmap_range_size-option.patch @@ -0,0 +1,37 @@ +From 33a029f9d2b55887fef08676234bebc4b6b5f7e4 Mon Sep 17 00:00:00 2001 +From: Pavel Reichl +Date: Thu, 28 Jan 2016 05:03:40 -0500 +Subject: [PATCH 59/86] IDMAP: Man change for ldap_idmap_range_size option +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Resolves: +https://fedorahosted.org/sssd/ticket/2922 + +Reviewed-by: Nathaniel McCallum +Reviewed-by: Michal Židek +(cherry picked from commit d9de4b26f44a344025bbfa23104b7b67935fae35) +(cherry picked from commit c2fa17edf4b9d385302ddd24ce599a1cef7250a6) +--- + src/man/include/ldap_id_mapping.xml | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/man/include/ldap_id_mapping.xml b/src/man/include/ldap_id_mapping.xml +index a088c4e81d81c5670edea8ae8081abe80927446a..9252b1caa56b086b640ab0b2a79069616cef6443 100644 +--- a/src/man/include/ldap_id_mapping.xml ++++ b/src/man/include/ldap_id_mapping.xml +@@ -178,7 +178,9 @@ ldap_schema = ad + + For example, if your most recently-added Active Directory user has + objectSid=S-1-5-21-2153326666-2176343378-3404031434-1107, +- ldap_idmap_range_size must be at least 1107. ++ ldap_idmap_range_size must be at least 1108 as ++ range size is equal to maximal SID minus minimal SID plus one ++ (e.g. 1108 = 1107 - 0 + 1). + + + It is important to plan ahead for future expansion, as changing this +-- +2.5.0 + diff --git a/0060-NSS-Fix-memory-leak-netgroup.patch b/0060-NSS-Fix-memory-leak-netgroup.patch new file mode 100644 index 0000000..bd4c380 --- /dev/null +++ b/0060-NSS-Fix-memory-leak-netgroup.patch @@ -0,0 +1,107 @@ +From df9da4a4d83e1ebc235a2b5ead445e0a406c1234 Mon Sep 17 00:00:00 2001 +From: Pavel Reichl +Date: Fri, 27 Nov 2015 07:53:00 -0500 +Subject: [PATCH 60/86] NSS: Fix memory leak netgroup + +Resolves: +https://fedorahosted.org/sssd/ticket/2865 + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 4231a17e66e0809a9c3d42207b45f95429cbb46c) +(cherry picked from commit 3bca87239e3368d61c25f2f6bd2329191eca0dee) +--- + src/responder/nss/nsssrv_netgroup.c | 41 ++++++++++++++++++++++++++----------- + 1 file changed, 29 insertions(+), 12 deletions(-) + +diff --git a/src/responder/nss/nsssrv_netgroup.c b/src/responder/nss/nsssrv_netgroup.c +index 9a78c1119c2f4e06e43ebec29ace775adc997e08..383b44a2c9b1fb87d3abfdce071b226a561e22a7 100644 +--- a/src/responder/nss/nsssrv_netgroup.c ++++ b/src/responder/nss/nsssrv_netgroup.c +@@ -435,14 +435,18 @@ static errno_t create_negcache_netgr(struct setent_step_ctx *step_ctx) + errno_t ret; + struct getent_ctx *netgr; + +- netgr = talloc_zero(step_ctx->nctx, struct getent_ctx); +- if (netgr == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n"); +- ret = ENOMEM; +- goto done; +- } else { +- netgr->ready = true; +- netgr->found = false; ++ /* Is there already netgroup with such name? */ ++ ret = get_netgroup_entry(step_ctx->nctx, step_ctx->name, ++ &netgr); ++ if (ret != EOK || netgr == NULL) { ++ ++ netgr = talloc_zero(step_ctx->nctx, struct getent_ctx); ++ if (netgr == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ + netgr->entries = NULL; + netgr->lookup_table = step_ctx->nctx->netgroups; + netgr->name = talloc_strdup(netgr, step_ctx->name); +@@ -457,13 +461,20 @@ static errno_t create_negcache_netgr(struct setent_step_ctx *step_ctx) + DEBUG(SSSDBG_CRIT_FAILURE, "set_netgroup_entry failed.\n"); + goto done; + } +- set_netgr_lifetime(step_ctx->nctx->neg_timeout, step_ctx, netgr); + } + ++ netgr->ready = true; ++ netgr->found = false; ++ ++ set_netgr_lifetime(step_ctx->nctx->neg_timeout, step_ctx, netgr); ++ ++ ret = EOK; ++ + done: + if (ret != EOK) { + talloc_free(netgr); + } ++ + return ret; + } + +@@ -474,6 +485,12 @@ static errno_t lookup_netgr_step(struct setent_step_ctx *step_ctx) + struct getent_ctx *netgr; + char *name = NULL; + uint32_t lifetime; ++ TALLOC_CTX *tmp_ctx; ++ ++ tmp_ctx = talloc_new(NULL); ++ if (tmp_ctx == NULL) { ++ return ENOMEM; ++ } + + /* Check each domain for this netgroup name */ + while (dom) { +@@ -494,8 +511,7 @@ static errno_t lookup_netgr_step(struct setent_step_ctx *step_ctx) + /* make sure to update the dctx if we changed domain */ + step_ctx->dctx->domain = dom; + +- talloc_free(name); +- name = sss_get_cased_name(step_ctx, step_ctx->name, ++ name = sss_get_cased_name(tmp_ctx, step_ctx->name, + dom->case_sensitive); + if (!name) { + DEBUG(SSSDBG_CRIT_FAILURE, "sss_get_cased_name failed\n"); +@@ -623,10 +639,11 @@ static errno_t lookup_netgr_step(struct setent_step_ctx *step_ctx) + "create_negcache_netgr failed with: %d:[%s], ignored.\n", + ret, sss_strerror(ret)); + } ++ + ret = ENOENT; + + done: +- talloc_free(name); ++ talloc_free(tmp_ctx); + return ret; + } + +-- +2.5.0 + diff --git a/0061-IDMAP-Add-test-to-validate-off-by-one-bug.patch b/0061-IDMAP-Add-test-to-validate-off-by-one-bug.patch new file mode 100644 index 0000000..ed23529 --- /dev/null +++ b/0061-IDMAP-Add-test-to-validate-off-by-one-bug.patch @@ -0,0 +1,189 @@ +From e3e319e537e6def0248351118f3801213b5a2475 Mon Sep 17 00:00:00 2001 +From: Pavel Reichl +Date: Fri, 22 Jan 2016 08:34:14 -0500 +Subject: [PATCH 61/86] IDMAP: Add test to validate off by one bug +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Resolves: +https://fedorahosted.org/sssd/ticket/2922 + +Reviewed-by: Pavel Březina +Reviewed-by: Lukáš Slebodník +Reviewed-by: Michal Židek +(cherry picked from commit 9d17f436795a36b1b1126f444923aa847fd0f93a) +(cherry picked from commit 8c1f3b27d8e20b271dfea0c41fd864e9af5476f5) +--- + src/tests/cmocka/test_sss_idmap.c | 113 ++++++++++++++++++++++++++++++++++++-- + 1 file changed, 109 insertions(+), 4 deletions(-) + +diff --git a/src/tests/cmocka/test_sss_idmap.c b/src/tests/cmocka/test_sss_idmap.c +index 00e03ffd9ab1532fb55795b9935b254c8a89ec16..f82e3dc51601850a480cf1daa6d5f6dbd940ddcb 100644 +--- a/src/tests/cmocka/test_sss_idmap.c ++++ b/src/tests/cmocka/test_sss_idmap.c +@@ -43,6 +43,9 @@ + #define TEST_OFFSET 1000000 + #define TEST_OFFSET_STR "1000000" + ++const int TEST_2922_MIN_ID = 1842600000; ++const int TEST_2922_MAX_ID = 1842799999; ++ + struct test_ctx { + TALLOC_CTX *mem_idmap; + struct sss_idmap_ctx *idmap_ctx; +@@ -128,7 +131,38 @@ static int setup_ranges(struct test_ctx *test_ctx, bool external_mapping, + return 0; + } + +-static int test_sss_idmap_setup_with_domains(void **state) { ++static int setup_ranges_2922(struct test_ctx *test_ctx) ++{ ++ const int TEST_2922_DFL_SLIDE = 9212; ++ struct sss_idmap_range range; ++ enum idmap_error_code err; ++ const char *name; ++ const char *sid; ++ /* Pick a new slice. */ ++ id_t slice_num = -1; ++ ++ assert_non_null(test_ctx); ++ ++ name = TEST_DOM_NAME; ++ sid = TEST_DOM_SID; ++ ++ err = sss_idmap_calculate_range(test_ctx->idmap_ctx, sid, &slice_num, ++ &range); ++ assert_int_equal(err, IDMAP_SUCCESS); ++ /* Range computation should be deterministic. Lets validate that. */ ++ assert_int_equal(range.min, TEST_2922_MIN_ID); ++ assert_int_equal(range.max, TEST_2922_MAX_ID); ++ assert_int_equal(slice_num, TEST_2922_DFL_SLIDE); ++ ++ err = sss_idmap_add_domain_ex(test_ctx->idmap_ctx, name, sid, &range, ++ NULL, 0, false /* No external mapping */); ++ assert_int_equal(err, IDMAP_SUCCESS); ++ ++ return 0; ++} ++ ++static int test_sss_idmap_setup_with_domains(void **state) ++{ + struct test_ctx *test_ctx; + + test_sss_idmap_setup(state); +@@ -140,7 +174,21 @@ static int test_sss_idmap_setup_with_domains(void **state) { + return 0; + } + +-static int test_sss_idmap_setup_with_domains_sec_slices(void **state) { ++static int test_sss_idmap_setup_with_domains_2922(void **state) ++{ ++ struct test_ctx *test_ctx; ++ ++ test_sss_idmap_setup(state); ++ ++ test_ctx = talloc_get_type(*state, struct test_ctx); ++ assert_non_null(test_ctx); ++ ++ setup_ranges_2922(test_ctx); ++ return 0; ++} ++ ++static int test_sss_idmap_setup_with_domains_sec_slices(void **state) ++{ + struct test_ctx *test_ctx; + + test_sss_idmap_setup(state); +@@ -152,7 +200,8 @@ static int test_sss_idmap_setup_with_domains_sec_slices(void **state) { + return 0; + } + +-static int test_sss_idmap_setup_with_external_mappings(void **state) { ++static int test_sss_idmap_setup_with_external_mappings(void **state) ++{ + struct test_ctx *test_ctx; + + test_sss_idmap_setup(state); +@@ -164,7 +213,8 @@ static int test_sss_idmap_setup_with_external_mappings(void **state) { + return 0; + } + +-static int test_sss_idmap_setup_with_both(void **state) { ++static int test_sss_idmap_setup_with_both(void **state) ++{ + struct test_ctx *test_ctx; + + test_sss_idmap_setup(state); +@@ -298,6 +348,58 @@ void test_map_id(void **state) + sss_idmap_free_sid(test_ctx->idmap_ctx, sid); + } + ++/* https://fedorahosted.org/sssd/ticket/2922 */ ++/* ID mapping - bug in computing max id for slice range */ ++void test_map_id_2922(void **state) ++{ ++ const char* TEST_2922_FIRST_SID = TEST_DOM_SID"-0"; ++ /* Last SID = first SID + (default) rangesize -1 */ ++ const char* TEST_2922_LAST_SID = TEST_DOM_SID"-199999"; ++ /* Last SID = first SID + rangesize */ ++ const char* TEST_2922_LAST_SID_PLUS_ONE = TEST_DOM_SID"-200000"; ++ struct test_ctx *test_ctx; ++ enum idmap_error_code err; ++ uint32_t id; ++ char *sid = NULL; ++ ++ test_ctx = talloc_get_type(*state, struct test_ctx); ++ ++ assert_non_null(test_ctx); ++ ++ /* Min UNIX ID to SID */ ++ err = sss_idmap_unix_to_sid(test_ctx->idmap_ctx, TEST_2922_MIN_ID, &sid); ++ assert_int_equal(err, IDMAP_SUCCESS); ++ assert_string_equal(sid, TEST_2922_FIRST_SID); ++ sss_idmap_free_sid(test_ctx->idmap_ctx, sid); ++ ++ /* First SID to UNIX ID */ ++ err = sss_idmap_sid_to_unix(test_ctx->idmap_ctx, TEST_2922_FIRST_SID, &id); ++ assert_int_equal(err, IDMAP_SUCCESS); ++ assert_int_equal(id, TEST_2922_MIN_ID); ++ ++ /* Max UNIX ID to SID */ ++ err = sss_idmap_unix_to_sid(test_ctx->idmap_ctx, TEST_2922_MAX_ID, &sid); ++ assert_int_equal(err, IDMAP_SUCCESS); ++ assert_string_equal(sid, TEST_2922_LAST_SID); ++ sss_idmap_free_sid(test_ctx->idmap_ctx, sid); ++ ++ /* Last SID to UNIX ID */ ++ err = sss_idmap_sid_to_unix(test_ctx->idmap_ctx, TEST_2922_LAST_SID, &id); ++ assert_int_equal(err, IDMAP_SUCCESS); ++ assert_int_equal(id, TEST_2922_MAX_ID); ++ ++ /* Max UNIX ID + 1 to SID */ ++ err = sss_idmap_unix_to_sid(test_ctx->idmap_ctx, TEST_2922_MAX_ID + 1, ++ &sid); ++ assert_int_equal(err, IDMAP_NO_DOMAIN); ++ ++ /* Last SID + 1 to UNIX ID */ ++ err = sss_idmap_sid_to_unix(test_ctx->idmap_ctx, ++ TEST_2922_LAST_SID_PLUS_ONE, &id); ++ /* Auto adding new ranges is disable in this test. */ ++ assert_int_equal(err, IDMAP_NO_RANGE); ++} ++ + void test_map_id_sec_slices(void **state) + { + struct test_ctx *test_ctx; +@@ -589,6 +691,9 @@ int main(int argc, const char *argv[]) + cmocka_unit_test_setup_teardown(test_map_id, + test_sss_idmap_setup_with_domains, + test_sss_idmap_teardown), ++ cmocka_unit_test_setup_teardown(test_map_id_2922, ++ test_sss_idmap_setup_with_domains_2922, ++ test_sss_idmap_teardown), + cmocka_unit_test_setup_teardown(test_map_id_sec_slices, + test_sss_idmap_setup_with_domains_sec_slices, + test_sss_idmap_teardown), +-- +2.5.0 + diff --git a/0062-SDAP-Add-return-code-ERR_ACCOUNT_LOCKED.patch b/0062-SDAP-Add-return-code-ERR_ACCOUNT_LOCKED.patch new file mode 100644 index 0000000..ff98953 --- /dev/null +++ b/0062-SDAP-Add-return-code-ERR_ACCOUNT_LOCKED.patch @@ -0,0 +1,119 @@ +From 4f1dec56127c91c02908f40161cde42313ff93e4 Mon Sep 17 00:00:00 2001 +From: Pavel Reichl +Date: Fri, 5 Feb 2016 07:27:38 -0500 +Subject: [PATCH 62/86] SDAP: Add return code ERR_ACCOUNT_LOCKED +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add code to distinquish state when account is locked in Active +Directory server. + +Tested against Windows Server 2012 + +This patch is best effort only as decision whether account is actually +locked is based on parsing error message returned by AD. The format and +content of this error message might be subject of change in future +releases and also can be modified by AD administrators. + +If account is locked bind operation is expected to return following +error message: + +----------------------------------------------------------------------- +Invalid credentials(49), 80090308: LdapErr: DSID-0C0903C5, comment: +AcceptSecurityContext error, data 775, v23f0 +----------------------------------------------------------------------- + +Where sub string 'data 775' implies that account is locked +(ERROR_ACCOUNT_LOCKED_OUT) [1]. However the 80090308 (error code +0x80090308, SEC_E_INVALID_TOKEN) is the only guaranteed part of error +string [2]. + +Error message is described in further detail as [3]: +----------------------------------------------------------------------- +When the server fails an LDAP operation with an error, and the server +has sufficient resources to compute a string value for the errorMessage +field of the LDAPResult, it includes a string in the errorMessage field +of the LDAPResult (see [RFC2251] section 4.1.10). The string contains +further information about the error. + +The first eight characters of the errorMessage string are a 32-bit +integer, expressed in hexadecimal. Where protocol specifies the extended +error code "" there is no restriction on the value of the +32-bit integer. It is recommended that implementations use a Windows +error code for the 32-bit integer in this case in order to improve +usability of the directory for clients. Where protocol specifies an +extended error code which is a Windows error code, the 32-bit integer is +the specified Windows error code. Any data after the eighth character +is strictly informational and used only for debugging. Conformant +implementations need not put any value beyond the eighth character of +the errorMessage field. +----------------------------------------------------------------------- + +[1] https://msdn.microsoft.com/en-us/library/windows/desktop/ms681386%28v=vs.85%29.aspx +[2] https://social.msdn.microsoft.com/Forums/en-US/e1d600c8-60b7-4ed0-94cb-20ddd6c1a1c6/msadts-user-locking-password-policies?forum=os_windowsprotocols +[3] MS-ADTS 3.1.1.3.1.9 + https://msdn.microsoft.com/en-us/library/cc223253.aspx + +Resolves: +https://fedorahosted.org/sssd/ticket/2839 + +Reviewed-by: Jakub Hrozek +Reviewed-by: Alexander Bokovoy +Reviewed-by: Lukáš Slebodník +(cherry picked from commit ff275f4c0b8cc1a098dbd0c5f6d52d6a93cda597) +(cherry picked from commit 81cb4057920c6296b7f7e6b7c651fdb601ff0338) +--- + src/providers/data_provider.h | 2 ++ + src/providers/ldap/ldap_auth.c | 4 ++++ + src/providers/ldap/sdap_async_connection.c | 6 ++++++ + 3 files changed, 12 insertions(+) + +diff --git a/src/providers/data_provider.h b/src/providers/data_provider.h +index 39051b90c3aad96f62dcbb86a20bcfd8c954879b..7332b677d19f70f4736e4d0b68d55cdd3c67a4af 100644 +--- a/src/providers/data_provider.h ++++ b/src/providers/data_provider.h +@@ -182,6 +182,8 @@ struct pam_data { + bool offline_auth; + bool last_auth_saved; + int priv; ++ int account_locked; ++ + #ifdef USE_KEYRING + key_serial_t key_serial; + #endif +diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c +index 217e80fd07abc41f2594d19397783683d44600cd..2fab92e5d22a4dae870c5e9dde7ef162fc36cbe2 100644 +--- a/src/providers/ldap/ldap_auth.c ++++ b/src/providers/ldap/ldap_auth.c +@@ -1302,6 +1302,10 @@ static void sdap_pam_auth_done(struct tevent_req *req) + case ERR_PASSWORD_EXPIRED: + state->pd->pam_status = PAM_NEW_AUTHTOK_REQD; + break; ++ case ERR_ACCOUNT_LOCKED: ++ state->pd->account_locked = true; ++ state->pd->pam_status = PAM_PERM_DENIED; ++ break; + default: + state->pd->pam_status = PAM_SYSTEM_ERR; + dp_err = DP_ERR_FATAL; +diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c +index 85b7aaa5bf5acedf3511ffe6f8636be007d5a136..40256de99006815c97ee9390dfd2e997cf6fc072 100644 +--- a/src/providers/ldap/sdap_async_connection.c ++++ b/src/providers/ldap/sdap_async_connection.c +@@ -754,6 +754,12 @@ static void simple_bind_done(struct sdap_op *op, + + if (result == LDAP_SUCCESS) { + ret = EOK; ++ } else if (result == LDAP_INVALID_CREDENTIALS ++ && errmsg != NULL && strstr(errmsg, "data 775,") != NULL) { ++ /* Value 775 is described in ++ * https://msdn.microsoft.com/en-us/library/windows/desktop/ms681386%28v=vs.85%29.aspx ++ * for more details please see commit message. */ ++ ret = ERR_ACCOUNT_LOCKED; + } else { + ret = ERR_AUTH_FAILED; + } +-- +2.5.0 + diff --git a/0063-PAM-Pass-account-lockout-status-and-display-message.patch b/0063-PAM-Pass-account-lockout-status-and-display-message.patch new file mode 100644 index 0000000..be4c2ab --- /dev/null +++ b/0063-PAM-Pass-account-lockout-status-and-display-message.patch @@ -0,0 +1,198 @@ +From fdc7e4acad41e7f0dff4926690f14bf94c009e38 Mon Sep 17 00:00:00 2001 +From: Pavel Reichl +Date: Fri, 5 Feb 2016 07:31:45 -0500 +Subject: [PATCH 63/86] PAM: Pass account lockout status and display message + +Tested against Windows Server 2012. + +Resolves: +https://fedorahosted.org/sssd/ticket/2839 + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 4180d485829969d4626cc7d49d2b5f7146512f21) +(cherry picked from commit 1b9f294dab02e6bcd4ce54e3447648d3d664ceaa) +--- + src/confdb/confdb.h | 1 + + src/config/SSSDConfig/__init__.py.in | 1 + + src/config/etc/sssd.api.conf | 1 + + src/man/sssd.conf.5.xml | 21 +++++++++++++++++++++ + src/providers/dp_auth_util.c | 19 +++++++++++++++++++ + src/responder/pam/pamsrv_cmd.c | 31 +++++++++++++++++++++++-------- + 6 files changed, 66 insertions(+), 8 deletions(-) + +diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h +index c6a5e3f61d8bfd045eb2699d0f5e279cb7d89f86..6d8601b31cf4ce1a42f824a8400cef8c4ffadf9a 100644 +--- a/src/confdb/confdb.h ++++ b/src/confdb/confdb.h +@@ -117,6 +117,7 @@ + #define CONFDB_PAM_TRUSTED_USERS "pam_trusted_users" + #define CONFDB_PAM_PUBLIC_DOMAINS "pam_public_domains" + #define CONFDB_PAM_ACCOUNT_EXPIRED_MESSAGE "pam_account_expired_message" ++#define CONFDB_PAM_ACCOUNT_LOCKED_MESSAGE "pam_account_locked_message" + #define CONFDB_PAM_CERT_AUTH "pam_cert_auth" + #define CONFDB_PAM_CERT_DB_PATH "pam_cert_db_path" + #define CONFDB_PAM_P11_CHILD_TIMEOUT "p11_child_timeout" +diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in +index 6abdbc3a43cd4dbd74208efa8602b889f6e84d2b..09284fdd7c8e630b3745367b33b8ea0424ff466f 100644 +--- a/src/config/SSSDConfig/__init__.py.in ++++ b/src/config/SSSDConfig/__init__.py.in +@@ -90,6 +90,7 @@ option_strings = { + 'pam_trusted_users' : _('List of trusted uids or user\'s name'), + 'pam_public_domains' : _('List of domains accessible even for untrusted users.'), + 'pam_account_expired_message' : _('Message printed when user account is expired.'), ++ 'pam_account_locked_message' : _('Message printed when user account is locked.'), + 'p11_child_timeout' : _('How many seconds will pam_sss wait for p11_child to finish'), + + # [sudo] +diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf +index b6a396a75e564355d0828fa24858337eb06ff4bf..6e00a87918b4c3972c1f05e5d66d0fc8a71a5cf7 100644 +--- a/src/config/etc/sssd.api.conf ++++ b/src/config/etc/sssd.api.conf +@@ -60,6 +60,7 @@ get_domains_timeout = int, None, false + pam_trusted_users = str, None, false + pam_public_domains = str, None, false + pam_account_expired_message = str, None, false ++pam_account_locked_message = str, None, false + p11_child_timeout = int, None, false + + [sudo] +diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml +index 7b1c4f0fff9c042ce9ade2473bfe4582909212c4..cf2301f06d03b580f0bd5cea3567599af45eed02 100644 +--- a/src/man/sssd.conf.5.xml ++++ b/src/man/sssd.conf.5.xml +@@ -1024,6 +1024,27 @@ pam_account_expired_message = Account expired, please call help desk. + + + ++ pam_account_locked_message (string) ++ ++ ++ If user is authenticating and ++ account is locked then by default ++ 'Permission denied' is output. This output will ++ be changed to content of this variable if it is ++ set. ++ ++ ++ example: ++ ++pam_account_locked_message = Account locked, please call help desk. ++ ++ ++ ++ Default: none ++ ++ ++ ++ + p11_child_timeout (integer) + + +diff --git a/src/providers/dp_auth_util.c b/src/providers/dp_auth_util.c +index f8a30c5d4e6da7ce6ac28723032241e2458ea473..8e261ef5e4af7479ffce087370844caa1cad43d7 100644 +--- a/src/providers/dp_auth_util.c ++++ b/src/providers/dp_auth_util.c +@@ -160,6 +160,14 @@ bool dp_pack_pam_response(DBusMessage *msg, struct pam_data *pd) + return false; + } + ++ /* Append the lockout of account */ ++ dbret = dbus_message_iter_append_basic(&iter, ++ DBUS_TYPE_UINT32, ++ &pd->account_locked); ++ if (!dbret) { ++ return false; ++ } ++ + /* Create an array of response structures */ + dbret = dbus_message_iter_open_container(&iter, + DBUS_TYPE_ARRAY, "(uay)", +@@ -246,6 +254,17 @@ bool dp_unpack_pam_response(DBusMessage *msg, struct pam_data *pd, DBusError *db + return false; + } + ++ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "pam response format error.\n"); ++ return false; ++ } ++ dbus_message_iter_get_basic(&iter, &(pd->account_locked)); ++ ++ if (!dbus_message_iter_next(&iter)) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "pam response has too few arguments.\n"); ++ return false; ++ } ++ + /* After this point will be an array of pam data */ + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) { + DEBUG(SSSDBG_CRIT_FAILURE, "pam response format error.\n"); +diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c +index 38636088e63ede159df0bc9376c255d05bf7de0b..c4ea9cd3e8970db7d281086453d22f3218b05c47 100644 +--- a/src/responder/pam/pamsrv_cmd.c ++++ b/src/responder/pam/pamsrv_cmd.c +@@ -53,10 +53,10 @@ pam_get_last_online_auth_with_curr_token(struct sss_domain_info *domain, + + static void pam_reply(struct pam_auth_req *preq); + +-static errno_t pack_user_info_account_expired(TALLOC_CTX *mem_ctx, +- const char *user_error_message, +- size_t *resp_len, +- uint8_t **_resp) ++static errno_t pack_user_info_msg(TALLOC_CTX *mem_ctx, ++ const char *user_error_message, ++ size_t *resp_len, ++ uint8_t **_resp) + { + uint32_t resp_type = SSS_PAM_USER_INFO_ACCOUNT_EXPIRED; + size_t err_len; +@@ -83,14 +83,13 @@ static errno_t pack_user_info_account_expired(TALLOC_CTX *mem_ctx, + return EOK; + } + +-static void inform_account_expired(struct pam_data* pd, +- const char *pam_message) ++static void inform_user(struct pam_data* pd, const char *pam_message) + { + size_t msg_len; + uint8_t *msg; + errno_t ret; + +- ret = pack_user_info_account_expired(pd, pam_message, &msg_len, &msg); ++ ret = pack_user_info_msg(pd, pam_message, &msg_len, &msg); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "pack_user_info_account_expired failed.\n"); +@@ -601,6 +600,7 @@ static void pam_reply(struct pam_auth_req *preq) + time_t exp_date = -1; + time_t delay_until = -1; + char* pam_account_expired_message; ++ char* pam_account_locked_message; + int pam_verbosity; + + pd = preq->pd; +@@ -762,7 +762,22 @@ static void pam_reply(struct pam_auth_req *preq) + goto done; + } + +- inform_account_expired(pd, pam_account_expired_message); ++ inform_user(pd, pam_account_expired_message); ++ } ++ ++ if (pd->account_locked) { ++ ++ ret = confdb_get_string(pctx->rctx->cdb, pd, CONFDB_PAM_CONF_ENTRY, ++ CONFDB_PAM_ACCOUNT_LOCKED_MESSAGE, "", ++ &pam_account_locked_message); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_MINOR_FAILURE, ++ "Failed to get expiration message: %d:[%s].\n", ++ ret, sss_strerror(ret)); ++ goto done; ++ } ++ ++ inform_user(pd, pam_account_locked_message); + } + + ret = filter_responses(pctx->rctx->cdb, pd->resp_list); +-- +2.5.0 + diff --git a/0064-PAM-Fix-man-for-pam_account_-expired-locked-_message.patch b/0064-PAM-Fix-man-for-pam_account_-expired-locked-_message.patch new file mode 100644 index 0000000..5fa167e --- /dev/null +++ b/0064-PAM-Fix-man-for-pam_account_-expired-locked-_message.patch @@ -0,0 +1,65 @@ +From 03dde14c2cc236e20456f24910dae4308dc96f16 Mon Sep 17 00:00:00 2001 +From: Dan Lavu +Date: Fri, 5 Feb 2016 09:28:41 -0500 +Subject: [PATCH 64/86] PAM: Fix man for pam_account_{expired,locked}_message + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 09092b6535b711b9b734ed0c047c671de9e6cafd) +(cherry picked from commit ffe3df61d85c2890a31d627c5e6fe8890f1e26d8) +--- + src/man/sssd.conf.5.xml | 35 +++++++++++++++++++++++++++++------ + 1 file changed, 29 insertions(+), 6 deletions(-) + +diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml +index cf2301f06d03b580f0bd5cea3567599af45eed02..d7e324f457a42403133c9d25f34d702d703fc9b8 100644 +--- a/src/man/sssd.conf.5.xml ++++ b/src/man/sssd.conf.5.xml +@@ -1006,16 +1006,39 @@ fallback_homedir = /home/%u + pam_account_expired_message (string) + + +- If user is authenticating using SSH keys and +- account is expired then by default +- 'Permission denied' is output. This output will +- be changed to content of this variable if it is +- set. ++ Allows a custom expiration message to be set, ++ replacing the default 'Permission denied' ++ message. ++ ++ ++ Note: Please be aware that message is only ++ printed for the SSH service unless pam_verbostiy ++ is set to 3 (show all messages and debug ++ information). ++ ++ ++ example: ++ ++pam_account_expired_message = Account expired, please contact help desk. ++ ++ ++ ++ Default: none ++ ++ ++ ++ ++ pam_account_locked_message (string) ++ ++ ++ Allows a custom lockout message to be set, ++ replacing the default 'Permission denied' ++ message. + + + example: + +-pam_account_expired_message = Account expired, please call help desk. ++pam_account_locked_message = Account locked, please contact help desk. + + + +-- +2.5.0 + diff --git a/0065-UTIL-Backport-error-code-ERR_ACCOUNT_LOCKED.patch b/0065-UTIL-Backport-error-code-ERR_ACCOUNT_LOCKED.patch new file mode 100644 index 0000000..94fa389 --- /dev/null +++ b/0065-UTIL-Backport-error-code-ERR_ACCOUNT_LOCKED.patch @@ -0,0 +1,45 @@ +From 90933a2aa0bc149fd8a1ca4feef0527ddfcf7258 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Wed, 17 Feb 2016 17:58:10 +0100 +Subject: [PATCH 65/86] UTIL: Backport error code ERR_ACCOUNT_LOCKED +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Required by: +https://fedorahosted.org/sssd/ticket/2839 + +Reviewed-by: Michal Židek +(cherry picked from commit af717c5b022d5c28141333fc02d5d9e1f322505c) +--- + src/util/util_errors.c | 1 + + src/util/util_errors.h | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/src/util/util_errors.c b/src/util/util_errors.c +index 1d684d387b90b8db37609d5bc022e06fcac708f9..59ae63ab8d6e834a772349b162bf282f9a4f1c72 100644 +--- a/src/util/util_errors.c ++++ b/src/util/util_errors.c +@@ -82,6 +82,7 @@ struct err_string error_to_str[] = { + { "Address family not supported" }, /* ERR_ADDR_FAMILY_NOT_SUPPORTED */ + { "Message sender is the bus" }, /* ERR_SBUS_SENDER_BUS */ + { "Subdomain is inactive" }, /* ERR_SUBDOM_INACTIVE */ ++ { "Account is locked" }, /* ERR_ACCOUNT_LOCKED */ + { "AD renewal child failed" }, /* ERR_RENEWAL_CHILD */ + { "ERR_LAST" } /* ERR_LAST */ + }; +diff --git a/src/util/util_errors.h b/src/util/util_errors.h +index 5c02fdd8b4c6e0c59f7fd6f66a3fc8a8e48dc607..05791f2f08f107a8b4830b810b8826983763174f 100644 +--- a/src/util/util_errors.h ++++ b/src/util/util_errors.h +@@ -104,6 +104,7 @@ enum sssd_errors { + ERR_ADDR_FAMILY_NOT_SUPPORTED, + ERR_SBUS_SENDER_BUS, + ERR_SUBDOM_INACTIVE, ++ ERR_ACCOUNT_LOCKED, + ERR_RENEWAL_CHILD, + ERR_LAST /* ALWAYS LAST */ + }; +-- +2.5.0 + diff --git a/0066-sss_idmap-tests-Fix-segmentation-fault.patch b/0066-sss_idmap-tests-Fix-segmentation-fault.patch new file mode 100644 index 0000000..f337f0f --- /dev/null +++ b/0066-sss_idmap-tests-Fix-segmentation-fault.patch @@ -0,0 +1,51 @@ +From 5897690a889c6f2a11135d1ed33089409ddb8c57 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Wed, 17 Feb 2016 17:23:37 +0100 +Subject: [PATCH 66/86] sss_idmap-tests: Fix segmentation fault + +I can reproduce it only with clang. +But it's tipical off by one error. + +sh$ ./sss_idmap-tests +Running suite(s): IDMAP +Segmentation fault (core dumped) + +Running suite(s): IDMAP +==2644== Process terminating with default action of signal 11 (SIGSEGV) +==2644== Access not within mapped region at address 0xA08F430 +==2644== at 0x4C2CC53: strcmp (vg_replace_strmem.c:842) +==2644== by 0x4060DA: idmap_test_sid2uid_additional_secondary_slices (sss_idmap-tests.c:451) +==2644== by 0x503C78A: ??? (in /usr/lib64/libcheck.so.0.0.0) +==2644== by 0x503CB7C: srunner_run (in /usr/lib64/libcheck.so.0.0.0) +==2644== by 0x4061EE: main (sss_idmap-tests.c:965) +==2644== If you believe this happened as a result of a stack +==2644== overflow in your program's main thread (unlikely but +==2644== possible), you can try to increase the size of the +==2644== main thread stack using the --main-stacksize= flag. +==2644== The main thread stack size used in this run was 8388608. + +Reviewed-by: Sumit Bose +(cherry picked from commit 4f3a996561445ba82c854bb2b674f975f596e884) +(cherry picked from commit 999af61d6a55bf816d86dbfc94214383436b18d3) +--- + src/tests/sss_idmap-tests.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/tests/sss_idmap-tests.c b/src/tests/sss_idmap-tests.c +index 900b7bff1cd4f3c6f9cdffc4b012864d05e72913..885913645ed286636758f3f48a5a62d87cc9ab75 100644 +--- a/src/tests/sss_idmap-tests.c ++++ b/src/tests/sss_idmap-tests.c +@@ -427,8 +427,8 @@ START_TEST(idmap_test_sid2uid_additional_secondary_slices) + struct TALLOC_CTX *tmp_ctx; + const char *dom_prefix = "S-1-5-21-1-2-3"; + const int max_rid = 80; +- const char *sids[max_rid]; +- unsigned int ids[max_rid]; ++ const char *sids[max_rid + 1]; ++ unsigned int ids[max_rid + 1]; + + tmp_ctx = talloc_new(NULL); + fail_unless(tmp_ctx != NULL, "Out of memory."); +-- +2.5.0 + diff --git a/0067-krb5_child-Warn-if-user-cannot-read-krb5.conf.patch b/0067-krb5_child-Warn-if-user-cannot-read-krb5.conf.patch new file mode 100644 index 0000000..8a05ce4 --- /dev/null +++ b/0067-krb5_child-Warn-if-user-cannot-read-krb5.conf.patch @@ -0,0 +1,74 @@ +From 40ccad84a0558eb21ebd351ea837c5042fa38966 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Fri, 29 Jan 2016 13:30:49 +0100 +Subject: [PATCH 67/86] krb5_child: Warn if user cannot read krb5.conf +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Attached patch should siplify troubleshoting of +issues with permission of krb5.conf. It's not clear from +krb5_child.log even with full debug level. + +[sss_get_ccache_name_for_principal] (0x4000): + Location: [FILE:/tmp/krb5cc_12069_XXXXXX] +[sss_get_ccache_name_for_principal] (0x2000): + krb5_cc_cache_match failed: [-1765328243] + [Can't find client principal user@EXAMPLE.COM in cache collection] +[create_ccache] (0x0020): 735: [13][Permission denied] + +Resolves: +https://fedorahosted.org/sssd/ticket/2931 + +Reviewed-by: Michal Židek +(cherry picked from commit 38f251e531b1c68e70eaa98dfecaf78da5f36ccc) +(cherry picked from commit 760d655881e87f52db033a4a56b05fbe91dce146) +--- + src/providers/krb5/krb5_child.c | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c +index 619e76372f962279ddffadadc607d9bbb20fbffb..6fd88815a5224809c7c448198495ae009f47097e 100644 +--- a/src/providers/krb5/krb5_child.c ++++ b/src/providers/krb5/krb5_child.c +@@ -2572,6 +2572,29 @@ static krb5_error_code privileged_krb5_setup(struct krb5_req *kr, + return 0; + } + ++static void try_open_krb5_conf(void) ++{ ++ int fd; ++ int ret; ++ ++ fd = open("/etc/krb5.conf", O_RDONLY); ++ if (fd != -1) { ++ close(fd); ++ } else { ++ ret = errno; ++ if (ret == EACCES || ret == EPERM) { ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "User with uid:%"SPRIuid" gid:%"SPRIgid" cannot read " ++ "/etc/krb5.conf. It might cause problems\n", ++ geteuid(), getegid()); ++ } else { ++ DEBUG(SSSDBG_MINOR_FAILURE, ++ "Cannot open /etc/krb5.conf [%d]: %s\n", ++ ret, strerror(ret)); ++ } ++ } ++} ++ + int main(int argc, const char *argv[]) + { + struct krb5_req *kr = NULL; +@@ -2673,6 +2696,7 @@ int main(int argc, const char *argv[]) + + DEBUG(SSSDBG_TRACE_INTERNAL, + "Running as [%"SPRIuid"][%"SPRIgid"].\n", geteuid(), getegid()); ++ try_open_krb5_conf(); + + ret = k5c_setup(kr, offline); + if (ret != EOK) { +-- +2.5.0 + diff --git a/0068-Fix-typos-reported-by-lintian.patch b/0068-Fix-typos-reported-by-lintian.patch new file mode 100644 index 0000000..80a7dcf --- /dev/null +++ b/0068-Fix-typos-reported-by-lintian.patch @@ -0,0 +1,197 @@ +From 7832b422ec442ec2d80cf00bb1189ac2f38a783b Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Fri, 12 Feb 2016 22:05:21 +0100 +Subject: [PATCH 68/86] Fix typos reported by lintian +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Reviewed-by: Pavel Březina +(cherry picked from commit 42604cc8d11743febf5aa892cb3a7d3c32bfed48) +(cherry picked from commit 7870820e8b188d755fef9fb31ef95b518c0f905b) +--- + src/ldb_modules/memberof.c | 10 +++++----- + src/providers/krb5/krb5_utils.c | 2 +- + src/providers/ldap/sdap.c | 2 +- + src/python/pysss.c | 2 +- + src/responder/common/negcache.c | 2 +- + src/responder/nss/nsssrv_mmap_cache.c | 2 +- + src/responder/pam/pamsrv_p11.c | 2 +- + src/tools/tools_util.c | 2 +- + src/util/nscd.c | 6 +++--- + 9 files changed, 15 insertions(+), 15 deletions(-) + +diff --git a/src/ldb_modules/memberof.c b/src/ldb_modules/memberof.c +index 4d7b23ea1b95bed0ec5c7cc717b95e6da3cd0717..83d93196c34854d75fcd8ac91ad056f64b26b659 100644 +--- a/src/ldb_modules/memberof.c ++++ b/src/ldb_modules/memberof.c +@@ -411,7 +411,7 @@ static int mbof_add_fill_ghop_ex(struct mbof_add_ctx *add_ctx, + return LDB_SUCCESS; + + default: +- /* an error occured, return */ ++ /* an error occurred, return */ + return ret; + } + +@@ -911,7 +911,7 @@ static int mbof_add_operation(struct mbof_add_operation *addop) + break; + + default: +- /* an error occured, return */ ++ /* an error occurred, return */ + return ret; + } + +@@ -2133,7 +2133,7 @@ static int mbof_del_mod_entry(struct mbof_del_operation *delop) + is_user = false; + break; + default: +- /* an error occured, return */ ++ /* an error occurred, return */ + return ret; + } + +@@ -2457,7 +2457,7 @@ static int mbof_del_fill_muop(struct mbof_del_ctx *del_ctx, + return LDB_SUCCESS; + + default: +- /* an error occured, return */ ++ /* an error occurred, return */ + return ret; + } + +@@ -2520,7 +2520,7 @@ static int mbof_del_fill_ghop_ex(struct mbof_del_ctx *del_ctx, + return LDB_SUCCESS; + + default: +- /* an error occured, return */ ++ /* an error occurred, return */ + return ret; + } + +diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c +index 0b73880eca6015fc9dffa4a850b230afc5dfddfc..7fd490514a52f0bfa3f1ced75f2b6496a77dada6 100644 +--- a/src/providers/krb5/krb5_utils.c ++++ b/src/providers/krb5/krb5_utils.c +@@ -386,7 +386,7 @@ char *expand_ccname_template(TALLOC_CTX *mem_ctx, struct krb5child_req *kr, + rerun = true; + continue; + } else if (strncmp(n , S_EXP_EUID, L_EXP_EUID) == 0) { +- /* SSSD does not distinguish betwen uid and euid, ++ /* SSSD does not distinguish between uid and euid, + * so we treat both the same way */ + action = 'U'; + n += L_EXP_EUID - 1; +diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c +index f9b9ff7e6913c406547f36d341300b936e121693..c0863a6d5bbe4f8f074e25634cb5e236075ce55a 100644 +--- a/src/providers/ldap/sdap.c ++++ b/src/providers/ldap/sdap.c +@@ -1284,7 +1284,7 @@ int sdap_get_server_opts_from_rootdse(TALLOC_CTX *memctx, + break; + default: + DEBUG(SSSDBG_CRIT_FAILURE, +- "Unkown error (%d) checking rootdse!\n", ret); ++ "Unknown error (%d) checking rootdse!\n", ret); + } + } else { + if (!entry_usn_name) { +diff --git a/src/python/pysss.c b/src/python/pysss.c +index 50f80421739e579ff94e5b8d1c5b97433b460e06..6bd8f5a9261aefe5b8ca90998e14878dd3896eef 100644 +--- a/src/python/pysss.c ++++ b/src/python/pysss.c +@@ -461,7 +461,7 @@ static PyObject *py_sss_usermod(PySssLocalObject *self, + + if (lock && lock != DO_LOCK && lock != DO_UNLOCK) { + PyErr_SetString(PyExc_ValueError, +- "Unkown value for lock parameter"); ++ "Unknown value for lock parameter"); + goto fail; + } + +diff --git a/src/responder/common/negcache.c b/src/responder/common/negcache.c +index f7af9e0280737f6c89c3034e8b19a6ecd393d355..5b0517ceba85d6e35515a935423412314c218143 100644 +--- a/src/responder/common/negcache.c ++++ b/src/responder/common/negcache.c +@@ -806,7 +806,7 @@ errno_t sss_ncache_prepopulate(struct sss_nc_ctx *ncache, + + if (domainname && strcmp(domainname, dom->name)) { + DEBUG(SSSDBG_CRIT_FAILURE, +- "Mismatch betwen domain name (%s) and name " ++ "Mismatch between domain name (%s) and name " + "set in FQN (%s), skipping group %s\n", + dom->name, domainname, name); + continue; +diff --git a/src/responder/nss/nsssrv_mmap_cache.c b/src/responder/nss/nsssrv_mmap_cache.c +index 62f4c543c628712810b6dfbc669c586c39ca609d..f7f62733941cd3ae3b071d6d54c801f9be1ce800 100644 +--- a/src/responder/nss/nsssrv_mmap_cache.c ++++ b/src/responder/nss/nsssrv_mmap_cache.c +@@ -1348,7 +1348,7 @@ errno_t sss_mmap_cache_reinit(TALLOC_CTX *mem_ctx, size_t n_elem, + + if (mc_ctx == NULL || (*mc_ctx) == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, +- "Unable to re-init unitialized memory cache.\n"); ++ "Unable to re-init uninitialized memory cache.\n"); + return EINVAL; + } + +diff --git a/src/responder/pam/pamsrv_p11.c b/src/responder/pam/pamsrv_p11.c +index ad1670136dbf8efc41df6950af744ff8b06e6a11..7a8002c2828c14e55ef2d827e37398035a0c6726 100644 +--- a/src/responder/pam/pamsrv_p11.c ++++ b/src/responder/pam/pamsrv_p11.c +@@ -144,7 +144,7 @@ static errno_t parse_p11_child_response(TALLOC_CTX *mem_ctx, uint8_t *buf, + + if (buf_len < 0) { + DEBUG(SSSDBG_CRIT_FAILURE, +- "Error occured while reading data from p11_child.\n"); ++ "Error occurred while reading data from p11_child.\n"); + return EIO; + } + +diff --git a/src/tools/tools_util.c b/src/tools/tools_util.c +index 68f6588ea887da6391159fa59916fdece102472b..3112171a6c06a50b7099f1c1b58ea1ad581c7cb3 100644 +--- a/src/tools/tools_util.c ++++ b/src/tools/tools_util.c +@@ -324,7 +324,7 @@ fini: + * Check is path is owned by uid + * returns 0 - owns + * -1 - does not own +- * >0 - an error occured, error code ++ * >0 - an error occurred, error code + */ + static int is_owner(uid_t uid, const char *path) + { +diff --git a/src/util/nscd.c b/src/util/nscd.c +index f58aebcad69924bdd841a4bb51aedb0308237ac4..ab29f3d271970911a0c1467b83147ba4774c1ecb 100644 +--- a/src/util/nscd.c ++++ b/src/util/nscd.c +@@ -139,7 +139,7 @@ errno_t sss_nscd_parse_conf(const char *conf_path) + { + FILE *fp; + int ret = EOK; +- unsigned int occured = 0; ++ unsigned int occurred = 0; + char *line, *entry, *service, *enabled, *pad; + size_t linelen = 0; + +@@ -195,7 +195,7 @@ errno_t sss_nscd_parse_conf(const char *conf_path) + if (!strcmp(entry, "enable-cache") && + !strcmp(enabled, "yes")) { + +- occured |= sss_nscd_check_service(service); ++ occurred |= sss_nscd_check_service(service); + } + }; + +@@ -209,7 +209,7 @@ errno_t sss_nscd_parse_conf(const char *conf_path) + } + + ret = EOK; +- if (occured != 0) { ++ if (occurred != 0) { + ret = EEXIST; + goto done; + } +-- +2.5.0 + diff --git a/0069-UTIL-Use-prefix-for-debug-function.patch b/0069-UTIL-Use-prefix-for-debug-function.patch new file mode 100644 index 0000000..1785f6d --- /dev/null +++ b/0069-UTIL-Use-prefix-for-debug-function.patch @@ -0,0 +1,97 @@ +From f468d11fce4257bf3acc07b7f5a8d45cfbe52a60 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Mon, 11 Jan 2016 18:54:40 +0100 +Subject: [PATCH 69/86] UTIL: Use prefix for debug function +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Reviewed-by: Pavel Březina +(cherry picked from commit 2a44a8c6683cfea218ee5329bcfad953dfeb6746) +(cherry picked from commit 4772bb86902552cb2fc18c3127b74f8cde5252ea) +--- + src/util/debug.c | 12 ++++++------ + src/util/sss_semanage.c | 2 +- + src/util/util.h | 16 ++++++++-------- + 3 files changed, 15 insertions(+), 15 deletions(-) + +diff --git a/src/util/debug.c b/src/util/debug.c +index b6ab368db824bbd297dcb410c3e669d911ff0d33..570c80273c0bdda1cc8df0e6af825595cfa339e0 100644 +--- a/src/util/debug.c ++++ b/src/util/debug.c +@@ -206,11 +206,11 @@ journal_done: + } + #endif /* WiTH_JOURNALD */ + +-void debug_fn(const char *file, +- long line, +- const char *function, +- int level, +- const char *format, ...) ++void sss_debug_fn(const char *file, ++ long line, ++ const char *function, ++ int level, ++ const char *format, ...) + { + va_list ap; + struct timeval tv; +@@ -301,7 +301,7 @@ void ldb_debug_messages(void *context, enum ldb_debug_level level, + } + + if (DEBUG_IS_SET(loglevel)) +- debug_fn(__FILE__, __LINE__, "ldb", loglevel, "%s\n", message); ++ sss_debug_fn(__FILE__, __LINE__, "ldb", loglevel, "%s\n", message); + + free(message); + } +diff --git a/src/util/sss_semanage.c b/src/util/sss_semanage.c +index d1d03988c05dc011dbd465051d50fe6acca4f845..4fb9df589bbfddcc815ed321b6e3b32655d44a0c 100644 +--- a/src/util/sss_semanage.c ++++ b/src/util/sss_semanage.c +@@ -64,7 +64,7 @@ static void sss_semanage_error_callback(void *varg, + } + + if (DEBUG_IS_SET(level)) +- debug_fn(__FILE__, __LINE__, "libsemanage", level, "%s\n", message); ++ sss_debug_fn(__FILE__, __LINE__, "libsemanage", level, "%s\n", message); + free(message); + } + +diff --git a/src/util/util.h b/src/util/util.h +index c0db6779f7f6fae44a5d956ae52a166f0f4eefc6..0b50d5abf6f1651dcf350e2c235702b5a21536d1 100644 +--- a/src/util/util.h ++++ b/src/util/util.h +@@ -71,11 +71,11 @@ extern int debug_microseconds; + extern int debug_to_file; + extern int debug_to_stderr; + extern const char *debug_log_file; +-void debug_fn(const char *file, +- long line, +- const char *function, +- int level, +- const char *format, ...) SSS_ATTRIBUTE_PRINTF(5,6); ++void sss_debug_fn(const char *file, ++ long line, ++ const char *function, ++ int level, ++ const char *format, ...) SSS_ATTRIBUTE_PRINTF(5, 6); + int debug_convert_old_level(int old_level); + errno_t set_debug_file_from_fd(const int fd); + int get_fd_from_debug_file(void); +@@ -129,9 +129,9 @@ int get_fd_from_debug_file(void); + #define DEBUG(level, format, ...) do { \ + int __debug_macro_level = level; \ + if (DEBUG_IS_SET(__debug_macro_level)) { \ +- debug_fn(__FILE__, __LINE__, __FUNCTION__, \ +- __debug_macro_level, \ +- format, ##__VA_ARGS__); \ ++ sss_debug_fn(__FILE__, __LINE__, __FUNCTION__, \ ++ __debug_macro_level, \ ++ format, ##__VA_ARGS__); \ + } \ + } while (0) + +-- +2.5.0 + diff --git a/0070-UTIL-Provide-varargs-version-of-debug_fn.patch b/0070-UTIL-Provide-varargs-version-of-debug_fn.patch new file mode 100644 index 0000000..349b301 --- /dev/null +++ b/0070-UTIL-Provide-varargs-version-of-debug_fn.patch @@ -0,0 +1,97 @@ +From 55928e9989e53b8333ce44cded97ce244b5ce048 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Mon, 11 Jan 2016 11:06:22 +0100 +Subject: [PATCH 70/86] UTIL: Provide varargs version of debug_fn +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Reviewed-by: Pavel Březina +(cherry picked from commit 22bbd95a48d21452fa5bb1a96b43334503bf8132) +(cherry picked from commit c99096a5f0a6e47c50e91ecd9ebbdf2a18195fa8) +--- + src/util/debug.c | 29 +++++++++++++++++++---------- + src/util/util.h | 6 ++++++ + 2 files changed, 25 insertions(+), 10 deletions(-) + +diff --git a/src/util/debug.c b/src/util/debug.c +index 570c80273c0bdda1cc8df0e6af825595cfa339e0..1b7aef467ff336e3316ab39f3a7d0b22ff3a0ed0 100644 +--- a/src/util/debug.c ++++ b/src/util/debug.c +@@ -206,13 +206,13 @@ journal_done: + } + #endif /* WiTH_JOURNALD */ + +-void sss_debug_fn(const char *file, +- long line, +- const char *function, +- int level, +- const char *format, ...) ++void sss_vdebug_fn(const char *file, ++ long line, ++ const char *function, ++ int level, ++ const char *format, ++ va_list ap) + { +- va_list ap; + struct timeval tv; + struct tm *tm; + char datetime[20]; +@@ -230,10 +230,8 @@ void sss_debug_fn(const char *file, + * can also provide extra structuring data to make it more easily + * searchable. + */ +- va_start(ap, format); + va_copy(ap_fallback, ap); + ret = journal_send(file, line, function, level, format, ap); +- va_end(ap); + if (ret != EOK) { + /* Emergency fallback, send to STDERR */ + debug_vprintf(format, ap_fallback); +@@ -266,12 +264,23 @@ void sss_debug_fn(const char *file, + debug_prg_name, function, level); + } + +- va_start(ap, format); + debug_vprintf(format, ap); +- va_end(ap); + debug_fflush(); + } + ++void sss_debug_fn(const char *file, ++ long line, ++ const char *function, ++ int level, ++ const char *format, ...) ++{ ++ va_list ap; ++ ++ va_start(ap, format); ++ sss_vdebug_fn(file, line, function, level, format, ap); ++ va_end(ap); ++} ++ + void ldb_debug_messages(void *context, enum ldb_debug_level level, + const char *fmt, va_list ap) + { +diff --git a/src/util/util.h b/src/util/util.h +index 0b50d5abf6f1651dcf350e2c235702b5a21536d1..9b5262995630b1b98f8658b3c32e1b83b0d31307 100644 +--- a/src/util/util.h ++++ b/src/util/util.h +@@ -71,6 +71,12 @@ extern int debug_microseconds; + extern int debug_to_file; + extern int debug_to_stderr; + extern const char *debug_log_file; ++void sss_vdebug_fn(const char *file, ++ long line, ++ const char *function, ++ int level, ++ const char *format, ++ va_list ap); + void sss_debug_fn(const char *file, + long line, + const char *function, +-- +2.5.0 + diff --git a/0071-UTIL-Use-sss_vdebug_fn-for-callbacks.patch b/0071-UTIL-Use-sss_vdebug_fn-for-callbacks.patch new file mode 100644 index 0000000..13d0b4a --- /dev/null +++ b/0071-UTIL-Use-sss_vdebug_fn-for-callbacks.patch @@ -0,0 +1,84 @@ +From 7b06c5415f24fe7d20253b101a6462d1944854d0 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Mon, 11 Jan 2016 19:13:06 +0100 +Subject: [PATCH 71/86] UTIL: Use sss_vdebug_fn for callbacks +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Reviewed-by: Pavel Březina +(cherry picked from commit f6c1f6a561bdd5b4bba03c02988a724da3dad387) +(cherry picked from commit 86ba562d09e1ee9aa55819d748722c2d3ac00600) +--- + src/util/debug.c | 13 ++----------- + src/util/sss_semanage.c | 14 +++----------- + 2 files changed, 5 insertions(+), 22 deletions(-) + +diff --git a/src/util/debug.c b/src/util/debug.c +index 1b7aef467ff336e3316ab39f3a7d0b22ff3a0ed0..03dc26d6d4e976866a3f9395598840e28997f69a 100644 +--- a/src/util/debug.c ++++ b/src/util/debug.c +@@ -285,8 +285,6 @@ void ldb_debug_messages(void *context, enum ldb_debug_level level, + const char *fmt, va_list ap) + { + int loglevel = SSSDBG_UNRESOLVED; +- int ret; +- char * message = NULL; + + switch(level) { + case LDB_DEBUG_FATAL: +@@ -303,16 +301,9 @@ void ldb_debug_messages(void *context, enum ldb_debug_level level, + break; + } + +- ret = vasprintf(&message, fmt, ap); +- if (ret < 0) { +- /* ENOMEM */ +- return; ++ if (DEBUG_IS_SET(loglevel)) { ++ sss_vdebug_fn(__FILE__, __LINE__, "ldb", loglevel, fmt, ap); + } +- +- if (DEBUG_IS_SET(loglevel)) +- sss_debug_fn(__FILE__, __LINE__, "ldb", loglevel, "%s\n", message); +- +- free(message); + } + + /* In cases SSSD used to run as the root user, but runs as the SSSD user now, +diff --git a/src/util/sss_semanage.c b/src/util/sss_semanage.c +index 4fb9df589bbfddcc815ed321b6e3b32655d44a0c..7f746491174730acbf1539acaf3f6467ff92afcf 100644 +--- a/src/util/sss_semanage.c ++++ b/src/util/sss_semanage.c +@@ -39,8 +39,6 @@ static void sss_semanage_error_callback(void *varg, + const char *fmt, ...) + { + int level = SSSDBG_INVALID; +- int ret; +- char * message = NULL; + va_list ap; + + switch (semanage_msg_get_level(handle)) { +@@ -56,16 +54,10 @@ static void sss_semanage_error_callback(void *varg, + } + + va_start(ap, fmt); +- ret = vasprintf(&message, fmt, ap); ++ if (DEBUG_IS_SET(level)) { ++ sss_vdebug_fn(__FILE__, __LINE__, "libsemanage", level, fmt, ap); ++ } + va_end(ap); +- if (ret < 0) { +- /* ENOMEM */ +- return; +- } +- +- if (DEBUG_IS_SET(level)) +- sss_debug_fn(__FILE__, __LINE__, "libsemanage", level, "%s\n", message); +- free(message); + } + + static void sss_semanage_close(semanage_handle_t *handle) +-- +2.5.0 + diff --git a/0072-Revert-DEBUG-Preventing-chown_debug_file-if-journald.patch b/0072-Revert-DEBUG-Preventing-chown_debug_file-if-journald.patch new file mode 100644 index 0000000..69b7fd6 --- /dev/null +++ b/0072-Revert-DEBUG-Preventing-chown_debug_file-if-journald.patch @@ -0,0 +1,75 @@ +From 910cd1c35859213319537072c48429e768b53b86 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Mon, 25 Jan 2016 11:46:54 +0100 +Subject: [PATCH 72/86] Revert "DEBUG: Preventing chown_debug_file if journald + on" + +This reverts commit 6e2822b151c21ce6e3287a0cf25d40e9f10a6127. + +The function chown_debug_file is called before initialization +of debug stuff in sssd. Therefore variable debug_file cannot be +initialized. Therefore reverted commit completely turned off +changing owner of debug files. Side effect of this change +was that annoying error messages was not logged in case of +journald. + +Resolves: +https://fedorahosted.org/sssd/ticket/2938 + +Reviewed-by: Jakub Hrozek +(cherry picked from commit 9f1186e7be7ece4d2b9bbbe444d3fc42ab57b808) +--- + src/util/debug.c | 35 ++++++++++++++++------------------- + 1 file changed, 16 insertions(+), 19 deletions(-) + +diff --git a/src/util/debug.c b/src/util/debug.c +index 03dc26d6d4e976866a3f9395598840e28997f69a..d10b456acd14f32590e8b4111596f95a555ac828 100644 +--- a/src/util/debug.c ++++ b/src/util/debug.c +@@ -316,27 +316,24 @@ int chown_debug_file(const char *filename, + const char *log_file; + errno_t ret; + +- if (debug_file) { ++ if (filename == NULL) { ++ log_file = debug_log_file; ++ } else { ++ log_file = filename; ++ } + +- if (filename == NULL) { +- log_file = debug_log_file; +- } else { +- log_file = filename; +- } ++ ret = asprintf(&logpath, "%s/%s.log", LOG_PATH, log_file); ++ if (ret == -1) { ++ return ENOMEM; ++ } + +- ret = asprintf(&logpath, "%s/%s.log", LOG_PATH, log_file); +- if (ret == -1) { +- return ENOMEM; +- } +- +- ret = chown(logpath, uid, gid); +- free(logpath); +- if (ret != 0) { +- ret = errno; +- DEBUG(SSSDBG_FATAL_FAILURE, "chown failed for [%s]: [%d]\n", +- log_file, ret); +- return ret; +- } ++ ret = chown(logpath, uid, gid); ++ free(logpath); ++ if (ret != 0) { ++ ret = errno; ++ DEBUG(SSSDBG_FATAL_FAILURE, "chown failed for [%s]: [%d]\n", ++ log_file, ret); ++ return ret; + } + + return EOK; +-- +2.5.0 + diff --git a/0073-DEBUG-Ignore-ENOENT-for-change-owner-of-log-files.patch b/0073-DEBUG-Ignore-ENOENT-for-change-owner-of-log-files.patch new file mode 100644 index 0000000..f7d2734 --- /dev/null +++ b/0073-DEBUG-Ignore-ENOENT-for-change-owner-of-log-files.patch @@ -0,0 +1,35 @@ +From 214a61d2169329106da654c06a5faaeaf645852d Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Fri, 22 Jan 2016 15:04:48 +0100 +Subject: [PATCH 73/86] DEBUG: Ignore ENOENT for change owner of log files + +Resolves: +https://fedorahosted.org/sssd/ticket/2493 + +Reviewed-by: Jakub Hrozek +(cherry picked from commit cbb04b9439d73fff027e193093a49cdac3cdb499) +--- + src/util/debug.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/src/util/debug.c b/src/util/debug.c +index d10b456acd14f32590e8b4111596f95a555ac828..a014bc3850641ad1f37c72df5a6181fed8391cfb 100644 +--- a/src/util/debug.c ++++ b/src/util/debug.c +@@ -331,6 +331,13 @@ int chown_debug_file(const char *filename, + free(logpath); + if (ret != 0) { + ret = errno; ++ if (ret == ENOENT) { ++ /* Log does not exist. We might log to journald ++ * or starting for first time. ++ * It's not a failure. */ ++ return EOK; ++ } ++ + DEBUG(SSSDBG_FATAL_FAILURE, "chown failed for [%s]: [%d]\n", + log_file, ret); + return ret; +-- +2.5.0 + diff --git a/0074-TOOLS-Fix-minor-memory-leak-in-sss_colondb_writeline.patch b/0074-TOOLS-Fix-minor-memory-leak-in-sss_colondb_writeline.patch new file mode 100644 index 0000000..93c6582 --- /dev/null +++ b/0074-TOOLS-Fix-minor-memory-leak-in-sss_colondb_writeline.patch @@ -0,0 +1,39 @@ +From dd7a1a508bdc60b62b5ef4ce22fcf31dace3f3c2 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Fri, 19 Feb 2016 16:18:02 +0100 +Subject: [PATCH 74/86] TOOLS: Fix minor memory leak in sss_colondb_writeline + +The variable line was initialized to NULL. +The we created temporary context tmp_ctx. +We use talloc_asprintf_append to append string to line which is initially +NULL and therefore new context which was not connected to tmp_ctx. + man 3 talloc_string -> talloc_asprintf_append + +Reviewed-by: Petr Cech +(cherry picked from commit 6977d7c84145ac69195be58b3330861b9b8a3b72) +(cherry picked from commit d75ac50d0c065974a7ec2330f60657ae85e487c0) +--- + src/tools/common/sss_colondb.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/src/tools/common/sss_colondb.c b/src/tools/common/sss_colondb.c +index a41b12fb9c097ff0e03da6d1c5cfe2fb24b63d54..b9af5f7e50c1166ca518a4e342637dc62518c567 100644 +--- a/src/tools/common/sss_colondb.c ++++ b/src/tools/common/sss_colondb.c +@@ -198,6 +198,13 @@ errno_t sss_colondb_writeline(struct sss_colondb *db, + return ENOMEM; + } + ++ line = talloc_strdup(tmp_ctx, ""); ++ if (line == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed.\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ + for (i = 0; table[i].type != SSS_COLONDB_SENTINEL; i++) { + switch (table[i].type) { + case SSS_COLONDB_UINT32: +-- +2.5.0 + diff --git a/0075-TOOLS-Fix-memory-leak-after-getline-failed.patch b/0075-TOOLS-Fix-memory-leak-after-getline-failed.patch new file mode 100644 index 0000000..64ac726 --- /dev/null +++ b/0075-TOOLS-Fix-memory-leak-after-getline-failed.patch @@ -0,0 +1,47 @@ +From 38bd263de5b83710898406640a77c15edea712fe Mon Sep 17 00:00:00 2001 +From: Petr Cech +Date: Thu, 18 Feb 2016 06:33:53 -0500 +Subject: [PATCH 75/86] TOOLS: Fix memory leak after getline() failed +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This patch fixes buffer freeing in case if getline() failed +in function sss_colondb_readline(). + +ssize_t getline(char **lineptr, size_t *n, FILE *stream); +If *lineptr is set to NULL and *n is set 0 before the call, then +getline() will allocate a buffer for storing the line. This buffer +should be freed by the user program even if getline() failed. + man 3 getline + +This patch fix buffer freeing in case if getline() failed. + +Resolves: +https://fedorahosted.org/sssd/ticket/2764 + +Reviewed-by: Lukáš Slebodník +(cherry picked from commit 2dd75ea79a57615808754c0ce550786edbc17d69) +(cherry picked from commit 34ba0c53d0d966c64ea11a6269cdd0ad985f4068) +--- + src/tools/common/sss_colondb.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/tools/common/sss_colondb.c b/src/tools/common/sss_colondb.c +index b9af5f7e50c1166ca518a4e342637dc62518c567..e8aeb315c9ed0efde15553e2d741d04c5d895b1a 100644 +--- a/src/tools/common/sss_colondb.c ++++ b/src/tools/common/sss_colondb.c +@@ -121,6 +121,10 @@ errno_t sss_colondb_readline(TALLOC_CTX *mem_ctx, + readchars = getline(&line, &linelen, db->file); + if (readchars == -1) { + /* Nothing was read. */ ++ ++ free(line); ++ line = NULL; ++ + if (errno != 0) { + ret = errno; + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to read line [%d]: %s\n", +-- +2.5.0 + diff --git a/0076-TOOLS-Add-comments-on-functions-in-colondb.patch b/0076-TOOLS-Add-comments-on-functions-in-colondb.patch new file mode 100644 index 0000000..12eefaa --- /dev/null +++ b/0076-TOOLS-Add-comments-on-functions-in-colondb.patch @@ -0,0 +1,74 @@ +From 3ca35b1781ef5a1f50c5165882b9ff4cebbbb7ac Mon Sep 17 00:00:00 2001 +From: Petr Cech +Date: Tue, 24 Nov 2015 10:34:10 -0500 +Subject: [PATCH 76/86] TOOLS: Add comments on functions in colondb +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The colondb API provides three function: +* sss_colondb_open() +* sss_colondb_write_field() +* sss_colondb_read_field() + +It is not obvious that sss_colondb_open() add destructor on talloc +context which close the colondb during free context. And there is +expectation that SSS_COLONDB_SENTINEL is type of last item in line. + +So this patch adds simple lightening comments in doxygen style. + +Resolves: +https://fedorahosted.org/sssd/ticket/2764 + +Reviewed-by: Lukáš Slebodník +(cherry picked from commit cf1109e30320a994187edeb438ac7cdc36f0dd2b) +(cherry picked from commit fbf7d5683287fa2c7b450b8f5b0df63673f25d83) +--- + src/tools/common/sss_colondb.h | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +diff --git a/src/tools/common/sss_colondb.h b/src/tools/common/sss_colondb.h +index 6edd99cbe3b9ef5c86a48632ac3fc71e8a3e55fe..cb9040088c65fdbe35c787b8942aaf1b14a2778d 100644 +--- a/src/tools/common/sss_colondb.h ++++ b/src/tools/common/sss_colondb.h +@@ -59,14 +59,37 @@ struct sss_colondb_read_field { + union sss_colondb_read_data data; + }; + ++/** ++ * Open colon DB and return connection. ++ * @param[in|out] mem_ctx Memory context. Internal sss_colondb_close() is set ++ * on destructor of this memory context. ++ * @param[in] mode Open mode of db: SSS_COLONDB_READ or SSS_COLONDB_WRITE. ++ * @param[in] filename Name of file. ++ * @return Pointer to structure holding DB connection, or NULL if fail. ++ */ + struct sss_colondb *sss_colondb_open(TALLOC_CTX *mem_ctx, + enum sss_colondb_mode mode, + const char *filename); + ++/** ++ * Read line from colon DB. ++ * @param[in|out] mem_ctx Memory context. ++ * @param[in] db Pointer to structure holding DB connection. ++ * @param[in|out] table Array of expected structure of line. It is expected ++ * that last item has SSS_COLONDB_SENTINEL type. ++ * @return EOK if success, else error code. ++ */ + errno_t sss_colondb_readline(TALLOC_CTX *mem_ctx, + struct sss_colondb *db, + struct sss_colondb_read_field *table); + ++/** ++ * Write line to colon DB. ++ * @param[in] db Pointer to structure holding DB connection. ++ * @param[in] table Array with data. It is expected that last item has ++ * SSS_COLONDB_SENTINEL type. ++ * @return EOK if success, else error code. ++ */ + errno_t sss_colondb_writeline(struct sss_colondb *db, + struct sss_colondb_write_field *table); + +-- +2.5.0 + diff --git a/0077-TEST_TOOLS_COLONDB-Add-tests-for-sss_colondb_.patch b/0077-TEST_TOOLS_COLONDB-Add-tests-for-sss_colondb_.patch new file mode 100644 index 0000000..4fa278f --- /dev/null +++ b/0077-TEST_TOOLS_COLONDB-Add-tests-for-sss_colondb_.patch @@ -0,0 +1,504 @@ +From eb2ce6f47fd9a676bf5405deda2ccfabc42a437c Mon Sep 17 00:00:00 2001 +From: Petr Cech +Date: Fri, 27 Nov 2015 06:39:37 -0500 +Subject: [PATCH 77/86] TEST_TOOLS_COLONDB: Add tests for sss_colondb_* +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +There are three functions at API of colondb wrapper: + * sss_colondb_open() + * sss_colondb_readline() + * sss_colondb_writeline() + +This patch adds tests for all of them. + +We test those cases: + * open nonexisting file for read + * open nonexisting file for write + * open existing empty file for read + * open existing file with records for read + * open existing empty file for write + * open existing file with records for write + * write to empty file + * write to file with existing records + * sss_colondb_open() + * sss_colondb_readline() + * sss_colondb_write_line() + * write to empty file and read it + +Resolves: +https://fedorahosted.org/sssd/ticket/2764 + +Reviewed-by: Lukáš Slebodník +(cherry picked from commit b590f44c06158485357d69cc5b24d5af05f1bb95) +(cherry picked from commit b269edafff139510ee1e9c00bdbc8f27e8aea691) +--- + Makefile.am | 17 ++ + src/tests/cmocka/test_tools_colondb.c | 419 ++++++++++++++++++++++++++++++++++ + 2 files changed, 436 insertions(+) + create mode 100644 src/tests/cmocka/test_tools_colondb.c + +diff --git a/Makefile.am b/Makefile.am +index 22653cfe08ca1fa42f551bdd585868a7e56046ba..9bd5d0ba895bf699c0b9a46f86419adbd266aece 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -241,6 +241,7 @@ if HAVE_CMOCKA + pam-srv-tests \ + test_ipa_subdom_util \ + test_ipa_subdom_server \ ++ test_tools_colondb \ + test_krb5_wait_queue \ + test_cert_utils \ + test_ldap_id_cleanup \ +@@ -2579,6 +2580,22 @@ test_ipa_subdom_server_LDADD = \ + libdlopen_test_providers.la \ + $(NULL) + ++test_tools_colondb_SOURCES = \ ++ src/tests/cmocka/test_tools_colondb.c \ ++ src/tools/common/sss_colondb.c \ ++ $(NULL) ++test_tools_colondb_CFLAGS = \ ++ $(AM_CFLAGS) \ ++ $(NULL) ++test_tools_colondb_LDFLAGS = \ ++ $(NULL) ++test_tools_colondb_LDADD = \ ++ $(CMOCKA_LIBS) \ ++ $(SSSD_INTERNAL_LTLIBS) \ ++ $(POPT_LIBS) \ ++ libsss_test_common.la \ ++ $(NULL) ++ + test_krb5_wait_queue_SOURCES = \ + src/tests/cmocka/common_mock_be.c \ + src/tests/cmocka/test_krb5_wait_queue.c \ +diff --git a/src/tests/cmocka/test_tools_colondb.c b/src/tests/cmocka/test_tools_colondb.c +new file mode 100644 +index 0000000000000000000000000000000000000000..5aa105896b3690127b5bf3241fe2b27d2ae2f920 +--- /dev/null ++++ b/src/tests/cmocka/test_tools_colondb.c +@@ -0,0 +1,419 @@ ++/* ++ Authors: ++ Petr Čech ++ ++ 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 "tests/cmocka/common_mock.h" ++#include "src/tools/common/sss_colondb.h" ++ ++#define TESTS_PATH "tp_" BASE_FILE_STEM ++#define TESTS_FILE "test_colondb.ldb" ++ ++const char *TEST_STRING1 = "white"; ++const int TEST_INT1 = 12; ++ ++const char *TEST_STRING2 = "black"; ++const int TEST_INT2 = 34; ++ ++static void create_dir(const char *path) ++{ ++ errno_t ret; ++ ++ errno = 0; ++ ret = mkdir(path, 0775); ++ assert_return_code(ret, errno); ++} ++ ++static void create_empty_file(TALLOC_CTX *test_ctx, const char *path, ++ const char *name) ++{ ++ TALLOC_CTX *tmp_ctx = NULL; ++ char *file_name = NULL; ++ FILE *fp = NULL; ++ ++ tmp_ctx = talloc_new(test_ctx); ++ assert_non_null(tmp_ctx); ++ ++ create_dir(path); ++ ++ file_name = talloc_asprintf(tmp_ctx, "%s/%s", path, name); ++ assert_non_null(file_name); ++ ++ fp = fopen(file_name, "w"); ++ assert_non_null(fp); ++ fclose(fp); ++ ++ talloc_free(tmp_ctx); ++} ++ ++static void create_nonempty_file(TALLOC_CTX *test_ctx, ++ const char *path, const char *name) ++{ ++ TALLOC_CTX *tmp_ctx = NULL; ++ struct sss_colondb *db = NULL; ++ errno_t ret; ++ struct sss_colondb_write_field table[] = { ++ { SSS_COLONDB_STRING, { .str = TEST_STRING2 } }, ++ { SSS_COLONDB_UINT32, { .uint32 = TEST_INT2 } }, ++ { SSS_COLONDB_SENTINEL, { 0 } } ++ }; ++ ++ tmp_ctx = talloc_new(test_ctx); ++ assert_non_null(tmp_ctx); ++ ++ create_empty_file(test_ctx, TESTS_PATH, TESTS_FILE); ++ ++ db = sss_colondb_open(tmp_ctx, SSS_COLONDB_WRITE, ++ TESTS_PATH "/" TESTS_FILE); ++ assert_non_null(db); ++ ++ ret = sss_colondb_writeline(db, table); ++ assert_int_equal(ret, EOK); ++ ++ talloc_free(db); ++ talloc_free(tmp_ctx); ++} ++ ++static int setup(void **state, int file_state) ++{ ++ TALLOC_CTX *test_ctx = NULL; ++ ++ assert_true(leak_check_setup()); ++ ++ check_leaks_push(global_talloc_context); ++ test_ctx = talloc_new(global_talloc_context); ++ assert_non_null(test_ctx); ++ ++ switch (file_state) { ++ case 0: ++ break; ++ case 1: ++ create_empty_file(test_ctx, TESTS_PATH, TESTS_FILE); ++ break; ++ case 2: ++ create_nonempty_file(test_ctx, TESTS_PATH, TESTS_FILE); ++ break; ++ default: ++ break; ++ } ++ ++ check_leaks_push(test_ctx); ++ *state = test_ctx; ++ ++ return 0; ++} ++ ++static int without_file_setup(void **state) ++{ ++ return setup(state, 0); ++} ++ ++static int with_empty_file_setup(void **state) ++{ ++ return setup(state, 1); ++} ++ ++static int with_nonempty_file_setup(void **state) ++{ ++ return setup(state, 2); ++} ++ ++static int teardown(void **state) ++{ ++ errno_t ret; ++ ++ errno = 0; ++ ret = unlink(TESTS_PATH "/" TESTS_FILE); ++ if (ret != 0) { ++ assert_int_equal(errno, ENOENT); ++ } ++ ++ assert_true(check_leaks_pop(*state)); ++ talloc_zfree(*state); ++ ++ test_dom_suite_cleanup(TESTS_PATH, NULL, NULL); ++ assert_true(check_leaks_pop(global_talloc_context)); ++ assert_true(leak_check_teardown()); ++ ++ return 0; ++} ++ ++void test_open_nonexist_for_read(void **state) ++{ ++ TALLOC_CTX *test_ctx = *state; ++ struct sss_colondb *db = NULL; ++ ++ db = sss_colondb_open(test_ctx, SSS_COLONDB_READ, ++ TESTS_PATH "/" TESTS_FILE); ++ assert_null(db); ++ talloc_free(db); ++} ++ ++void test_open_nonexist_for_write(void **state) ++{ ++ TALLOC_CTX *test_ctx = *state; ++ struct sss_colondb *db = NULL; ++ ++ db = sss_colondb_open(test_ctx, SSS_COLONDB_WRITE, ++ TESTS_PATH "/" TESTS_FILE); ++ assert_null(db); ++ talloc_free(db); ++} ++ ++void test_open_exist_for_read(void **state) ++{ ++ TALLOC_CTX *test_ctx = *state; ++ struct sss_colondb *db = NULL; ++ ++ db = sss_colondb_open(test_ctx, SSS_COLONDB_READ, ++ TESTS_PATH "/" TESTS_FILE); ++ assert_non_null(db); ++ talloc_free(db); ++} ++ ++void test_open_exist_for_write(void **state) ++{ ++ TALLOC_CTX *test_ctx = *state; ++ struct sss_colondb *db = NULL; ++ ++ db = sss_colondb_open(test_ctx, SSS_COLONDB_WRITE, ++ TESTS_PATH "/" TESTS_FILE); ++ assert_non_null(db); ++ talloc_free(db); ++} ++ ++void test_open_nonempty_for_read(void **state) ++{ ++ TALLOC_CTX *test_ctx = *state; ++ struct sss_colondb *db = NULL; ++ ++ db = sss_colondb_open(test_ctx, SSS_COLONDB_READ, ++ TESTS_PATH "/" TESTS_FILE); ++ assert_non_null(db); ++ talloc_free(db); ++} ++ ++void test_open_nonempty_for_write(void **state) ++{ ++ ++ TALLOC_CTX *test_ctx = *state; ++ struct sss_colondb *db = NULL; ++ ++ db = sss_colondb_open(test_ctx, SSS_COLONDB_WRITE, ++ TESTS_PATH "/" TESTS_FILE); ++ assert_non_null(db); ++ talloc_free(db); ++} ++ ++void test_write_to_empty(void **state) ++{ ++ TALLOC_CTX *test_ctx = *state; ++ struct sss_colondb *db = NULL; ++ struct sss_colondb_write_field table[] = { ++ { SSS_COLONDB_STRING, { .str = TEST_STRING1 } }, ++ { SSS_COLONDB_UINT32, { .uint32 = TEST_INT1 } }, ++ { SSS_COLONDB_SENTINEL, { 0 } } ++ }; ++ errno_t ret; ++ ++ db = sss_colondb_open(test_ctx, SSS_COLONDB_WRITE, ++ TESTS_PATH "/" TESTS_FILE); ++ assert_non_null(db); ++ ++ ret = sss_colondb_writeline(db, table); ++ assert_int_equal(ret, 0); ++ ++ talloc_free(db); ++} ++ ++void test_write_to_nonempty(void **state) ++{ ++ TALLOC_CTX *test_ctx = *state; ++ struct sss_colondb *db = NULL; ++ struct sss_colondb_write_field table[] = { ++ { SSS_COLONDB_STRING, { .str = TEST_STRING1 } }, ++ { SSS_COLONDB_UINT32, { .uint32 = TEST_INT1 } }, ++ { SSS_COLONDB_SENTINEL, { 0 } } ++ }; ++ errno_t ret; ++ ++ db = sss_colondb_open(test_ctx, SSS_COLONDB_WRITE, ++ TESTS_PATH "/" TESTS_FILE); ++ assert_non_null(db); ++ ++ ret = sss_colondb_writeline(db, table); ++ assert_int_equal(ret, 0); ++ ++ talloc_free(db); ++} ++ ++void test_read_from_nonempty(void **state) ++{ ++ TALLOC_CTX *test_ctx = *state; ++ struct sss_colondb *db = NULL; ++ errno_t ret; ++ const char *string = NULL; ++ uint32_t number; ++ struct sss_colondb_read_field table[] = { ++ { SSS_COLONDB_STRING, { .str = &string } }, ++ { SSS_COLONDB_UINT32, { .uint32 = &number } }, ++ { SSS_COLONDB_SENTINEL, { 0 } } ++ }; ++ ++ db = sss_colondb_open(test_ctx, SSS_COLONDB_READ, ++ TESTS_PATH "/" TESTS_FILE); ++ assert_non_null(db); ++ ++ ret = sss_colondb_readline(test_ctx, db, table); ++ assert_int_equal(ret, 0); ++ assert_string_equal(string, TEST_STRING2); ++ assert_int_equal(number, TEST_INT2); ++ ++ talloc_zfree(string); ++ talloc_free(db); ++} ++ ++void test_read_from_empty(void **state) ++{ ++ TALLOC_CTX *test_ctx = *state; ++ struct sss_colondb *db = NULL; ++ errno_t ret; ++ const char *string; ++ uint32_t number; ++ struct sss_colondb_read_field table[] = { ++ { SSS_COLONDB_STRING, { .str = &string } }, ++ { SSS_COLONDB_UINT32, { .uint32 = &number } }, ++ { SSS_COLONDB_SENTINEL, { 0 } } ++ }; ++ ++ db = sss_colondb_open(test_ctx, SSS_COLONDB_READ, ++ TESTS_PATH "/" TESTS_FILE); ++ assert_non_null(db); ++ ++ ret = sss_colondb_readline(test_ctx, db, table); ++ assert_int_equal(ret, EOF); ++ ++ talloc_free(db); ++} ++ ++void test_write_read(void **state) ++{ ++ TALLOC_CTX *test_ctx = *state; ++ struct sss_colondb *db = NULL; ++ errno_t ret; ++ const char *string = NULL; ++ uint32_t number; ++ struct sss_colondb_write_field table_in[] = { ++ { SSS_COLONDB_STRING, { .str = TEST_STRING2 } }, ++ { SSS_COLONDB_UINT32, { .uint32 = TEST_INT2 } }, ++ { SSS_COLONDB_SENTINEL, { 0 } } ++ }; ++ struct sss_colondb_read_field table_out[] = { ++ { SSS_COLONDB_STRING, { .str = &string } }, ++ { SSS_COLONDB_UINT32, { .uint32 = &number } }, ++ { SSS_COLONDB_SENTINEL, { 0 } } ++ }; ++ ++ db = sss_colondb_open(test_ctx, SSS_COLONDB_WRITE, ++ TESTS_PATH "/" TESTS_FILE); ++ assert_non_null(db); ++ ++ ret = sss_colondb_writeline(db, table_in); ++ assert_int_equal(ret, 0); ++ ++ talloc_free(db); ++ ++ db = sss_colondb_open(test_ctx, SSS_COLONDB_READ, ++ TESTS_PATH "/" TESTS_FILE); ++ assert_non_null(db); ++ ++ ret = sss_colondb_readline(test_ctx, db, table_out); ++ assert_int_equal(ret, 0); ++ assert_string_equal(string, TEST_STRING2); ++ assert_int_equal(number, TEST_INT2); ++ ++ talloc_zfree(string); ++ talloc_free(db); ++} ++ ++int main(int argc, const char *argv[]) ++{ ++ poptContext pc; ++ int opt; ++ struct poptOption long_options[] = { ++ POPT_AUTOHELP ++ SSSD_DEBUG_OPTS ++ POPT_TABLEEND ++ }; ++ ++ const struct CMUnitTest tests[] = { ++ cmocka_unit_test_setup_teardown(test_open_nonexist_for_read, ++ without_file_setup, teardown), ++ cmocka_unit_test_setup_teardown(test_open_nonexist_for_write, ++ without_file_setup, teardown), ++ cmocka_unit_test_setup_teardown(test_open_exist_for_read, ++ with_empty_file_setup, teardown), ++ cmocka_unit_test_setup_teardown(test_open_exist_for_write, ++ with_empty_file_setup, teardown), ++ cmocka_unit_test_setup_teardown(test_open_nonempty_for_read, ++ with_nonempty_file_setup, teardown), ++ cmocka_unit_test_setup_teardown(test_open_nonempty_for_write, ++ with_nonempty_file_setup, teardown), ++ ++ cmocka_unit_test_setup_teardown(test_write_to_empty, ++ with_empty_file_setup, teardown), ++ cmocka_unit_test_setup_teardown(test_write_to_nonempty, ++ with_nonempty_file_setup, teardown), ++ ++ cmocka_unit_test_setup_teardown(test_read_from_empty, ++ with_empty_file_setup, teardown), ++ cmocka_unit_test_setup_teardown(test_read_from_nonempty, ++ with_nonempty_file_setup, teardown), ++ ++ cmocka_unit_test_setup_teardown(test_write_read, ++ with_empty_file_setup, teardown), ++ }; ++ ++ /* Set debug level to invalid value so we can decide 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); ++ ++ /* Even though normally the tests should clean up after themselves ++ * they might not after a failed run. Remove the old db to be sure */ ++ tests_set_cwd(); ++ test_dom_suite_cleanup(TESTS_PATH, NULL, NULL); ++ ++ return cmocka_run_group_tests(tests, NULL, NULL); ++} +-- +2.5.0 + diff --git a/0078-Add-a-new-option-ldap_group_external_member.patch b/0078-Add-a-new-option-ldap_group_external_member.patch new file mode 100644 index 0000000..b7e7eef --- /dev/null +++ b/0078-Add-a-new-option-ldap_group_external_member.patch @@ -0,0 +1,178 @@ +From 7dcecb5e2fb9fe83c3bbf52306e7c2b0365ff96d Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Mon, 25 Jan 2016 16:03:23 +0100 +Subject: [PATCH 78/86] Add a new option ldap_group_external_member + +Required for: + https://fedorahosted.org/sssd/ticket/2522 + +Reviewed-by: Sumit Bose +(cherry picked from commit 3cf7fdfcaedb986f42a6640e26aa057007b64045) +(cherry picked from commit 7db3bdfd6b1b845866c1ff062d25de5804141e89) +--- + src/config/SSSDConfig/__init__.py.in | 1 + + src/config/etc/sssd.api.d/sssd-ad.conf | 1 + + src/config/etc/sssd.api.d/sssd-ipa.conf | 1 + + src/config/etc/sssd.api.d/sssd-ldap.conf | 1 + + src/db/sysdb.h | 1 + + src/man/sssd-ldap.5.xml | 16 ++++++++++++++++ + src/providers/ad/ad_opts.c | 1 + + src/providers/ipa/ipa_opts.c | 1 + + src/providers/ldap/ldap_opts.c | 3 +++ + src/providers/ldap/sdap.h | 1 + + 10 files changed, 27 insertions(+) + +diff --git a/src/config/SSSDConfig/__init__.py.in b/src/config/SSSDConfig/__init__.py.in +index 09284fdd7c8e630b3745367b33b8ea0424ff466f..a400c831eb0e44f562c010f2a3649def21913287 100644 +--- a/src/config/SSSDConfig/__init__.py.in ++++ b/src/config/SSSDConfig/__init__.py.in +@@ -333,6 +333,7 @@ option_strings = { + 'ldap_group_objectsid' : _("objectSID attribute"), + 'ldap_group_modify_timestamp' : _('Modification time attribute for groups'), + 'ldap_group_type' : _('Type of the group and other flags'), ++ 'ldap_group_external_member' : _('The LDAP group external member attribute'), + #replaced by ldap_entry_usn# 'ldap_group_entry_usn' : _('entryUSN attribute'), + 'ldap_group_nesting_level' : _('Maximum nesting level SSSd will follow'), + +diff --git a/src/config/etc/sssd.api.d/sssd-ad.conf b/src/config/etc/sssd.api.d/sssd-ad.conf +index 149590f4f30de3438f2fc5534ae65c98ee0f10ad..23006d26ca6fe7ca2b912ef091b4c73d5d23bee1 100644 +--- a/src/config/etc/sssd.api.d/sssd-ad.conf ++++ b/src/config/etc/sssd.api.d/sssd-ad.conf +@@ -110,6 +110,7 @@ ldap_group_objectsid = str, None, false + ldap_group_modify_timestamp = str, None, false + ldap_group_entry_usn = str, None, false + ldap_group_type = int, None, false ++ldap_group_external_member = str, None, false + ldap_force_upper_case_realm = bool, None, false + ldap_group_nesting_level = int, None, false + ldap_netgroup_search_base = str, None, false +diff --git a/src/config/etc/sssd.api.d/sssd-ipa.conf b/src/config/etc/sssd.api.d/sssd-ipa.conf +index 822599db6390ad2244a71db770c0b162345a3321..8cd20c0c621a513ca7bc85be6908de41d024b148 100644 +--- a/src/config/etc/sssd.api.d/sssd-ipa.conf ++++ b/src/config/etc/sssd.api.d/sssd-ipa.conf +@@ -104,6 +104,7 @@ ldap_group_objectsid = str, None, false + ldap_group_modify_timestamp = str, None, false + ldap_group_entry_usn = str, None, false + ldap_group_type = int, None, false ++ldap_group_external_member = str, None, false + ldap_force_upper_case_realm = bool, None, false + ldap_group_nesting_level = int, None, false + ldap_netgroup_search_base = str, None, false +diff --git a/src/config/etc/sssd.api.d/sssd-ldap.conf b/src/config/etc/sssd.api.d/sssd-ldap.conf +index fc9fcefce94891760a3f3ada4c044dbcaf156945..8b52f268af195bc68d45389cda52a0ad0aba1aa3 100644 +--- a/src/config/etc/sssd.api.d/sssd-ldap.conf ++++ b/src/config/etc/sssd.api.d/sssd-ldap.conf +@@ -98,6 +98,7 @@ ldap_group_objectsid = str, None, false + ldap_group_modify_timestamp = str, None, false + ldap_group_entry_usn = str, None, false + ldap_group_type = int, None, false ++ldap_group_external_member = str, None, false + ldap_group_nesting_level = int, None, false + ldap_force_upper_case_realm = bool, None, false + ldap_netgroup_search_base = str, None, false +diff --git a/src/db/sysdb.h b/src/db/sysdb.h +index 2e797fd7fa39163c2ab6a10e51228e0f1af3f9e3..95a9086766228a6c36c56d3a68a0bb0e493c0cbe 100644 +--- a/src/db/sysdb.h ++++ b/src/db/sysdb.h +@@ -81,6 +81,7 @@ + #define SYSDB_USER_CATEGORY "userCategory" + #define SYSDB_HOST_CATEGORY "hostCategory" + #define SYSDB_GROUP_TYPE "groupType" ++#define SYSDB_EXTERNAL_MEMBER "externalMember" + + #define SYSDB_GECOS "gecos" + #define SYSDB_LAST_LOGIN "lastLogin" +diff --git a/src/man/sssd-ldap.5.xml b/src/man/sssd-ldap.5.xml +index 66b9024bcdc6faced67c4e44f9cde7caa9a5ecc8..a30100408c6e77f9156878cb6ff63dfbf7b041d1 100644 +--- a/src/man/sssd-ldap.5.xml ++++ b/src/man/sssd-ldap.5.xml +@@ -942,6 +942,22 @@ + + + ++ ldap_group_external_member (string) ++ ++ ++ The LDAP attribute that references group ++ members that are defined in an external ++ domain. At the moment, only IPA's external ++ members are supported. ++ ++ ++ Default: ipaExternalMember in the IPA provider, ++ otherwise unset. ++ ++ ++ ++ ++ + ldap_group_nesting_level (integer) + + +diff --git a/src/providers/ad/ad_opts.c b/src/providers/ad/ad_opts.c +index 28d4768b20bd035f7c1971c95f9b6b690844816e..15024adb7959de9e16cdc92ca30daa74bb5f648d 100644 +--- a/src/providers/ad/ad_opts.c ++++ b/src/providers/ad/ad_opts.c +@@ -233,6 +233,7 @@ struct sdap_attr_map ad_2008r2_group_map[] = { + { "ldap_group_modify_timestamp", "whenChanged", SYSDB_ORIG_MODSTAMP, NULL }, + { "ldap_group_entry_usn", SDAP_AD_USN, SYSDB_USN, NULL }, + { "ldap_group_type", "groupType", SYSDB_GROUP_TYPE, NULL }, ++ { "ldap_group_external_member", NULL, SYSDB_EXTERNAL_MEMBER, NULL }, + SDAP_ATTR_MAP_TERMINATOR + }; + +diff --git a/src/providers/ipa/ipa_opts.c b/src/providers/ipa/ipa_opts.c +index cd87852e5891fd43d7ec728f76860f3050a54d2f..fe469852b527ad872502b3346c8c11ef9eea3bcd 100644 +--- a/src/providers/ipa/ipa_opts.c ++++ b/src/providers/ipa/ipa_opts.c +@@ -219,6 +219,7 @@ struct sdap_attr_map ipa_group_map[] = { + { "ldap_group_modify_timestamp", "modifyTimestamp", SYSDB_ORIG_MODSTAMP, NULL }, + { "ldap_group_entry_usn", NULL, SYSDB_USN, NULL }, + { "ldap_group_type", NULL, SYSDB_GROUP_TYPE, NULL }, ++ { "ldap_group_external_member", "ipaExternalMember", SYSDB_EXTERNAL_MEMBER, NULL }, + SDAP_ATTR_MAP_TERMINATOR + }; + +diff --git a/src/providers/ldap/ldap_opts.c b/src/providers/ldap/ldap_opts.c +index 84ba2b54271bcb6650e0336131ace8bfc1a40fc8..ff9bf0d8b6d4a8f677e08219e5105e3750b7a4a8 100644 +--- a/src/providers/ldap/ldap_opts.c ++++ b/src/providers/ldap/ldap_opts.c +@@ -195,6 +195,7 @@ struct sdap_attr_map rfc2307_group_map[] = { + { "ldap_group_modify_timestamp", "modifyTimestamp", SYSDB_ORIG_MODSTAMP, NULL }, + { "ldap_group_entry_usn", NULL, SYSDB_USN, NULL }, + { "ldap_group_type", NULL, SYSDB_GROUP_TYPE, NULL }, ++ { "ldap_group_external_member", NULL, SYSDB_EXTERNAL_MEMBER, NULL }, + SDAP_ATTR_MAP_TERMINATOR + }; + +@@ -251,6 +252,7 @@ struct sdap_attr_map rfc2307bis_group_map[] = { + { "ldap_group_modify_timestamp", "modifyTimestamp", SYSDB_ORIG_MODSTAMP, NULL }, + { "ldap_group_entry_usn", NULL, SYSDB_USN, NULL }, + { "ldap_group_type", NULL, SYSDB_GROUP_TYPE, NULL }, ++ { "ldap_group_external_member", NULL, SYSDB_EXTERNAL_MEMBER, NULL }, + SDAP_ATTR_MAP_TERMINATOR + }; + +@@ -307,6 +309,7 @@ struct sdap_attr_map gen_ad2008r2_group_map[] = { + { "ldap_group_modify_timestamp", "whenChanged", SYSDB_ORIG_MODSTAMP, NULL }, + { "ldap_group_entry_usn", SDAP_AD_USN, SYSDB_USN, NULL }, + { "ldap_group_type", "groupType", SYSDB_GROUP_TYPE, NULL }, ++ { "ldap_group_external_member", NULL, SYSDB_EXTERNAL_MEMBER, NULL }, + SDAP_ATTR_MAP_TERMINATOR + }; + +diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h +index e06f2b6ac47990f21985fb86f8ad3f3ae5a74df3..9dc2e16a0da76246a1f4492cf70e9124edba4a31 100644 +--- a/src/providers/ldap/sdap.h ++++ b/src/providers/ldap/sdap.h +@@ -304,6 +304,7 @@ enum sdap_group_attrs { + SDAP_AT_GROUP_MODSTAMP, + SDAP_AT_GROUP_USN, + SDAP_AT_GROUP_TYPE, ++ SDAP_AT_GROUP_EXT_MEMBER, + + SDAP_OPTS_GROUP /* attrs counter */ + }; +-- +2.5.0 + diff --git a/0079-IPA-Add-interface-to-call-into-IPA-provider-from-LDA.patch b/0079-IPA-Add-interface-to-call-into-IPA-provider-from-LDA.patch new file mode 100644 index 0000000..4dd469c --- /dev/null +++ b/0079-IPA-Add-interface-to-call-into-IPA-provider-from-LDA.patch @@ -0,0 +1,446 @@ +From 3725d2a83ae64be47c1bb645933f3a2abc91bd08 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Mon, 25 Jan 2016 16:11:59 +0100 +Subject: [PATCH 79/86] IPA: Add interface to call into IPA provider from LDAP + provider + +https://fedorahosted.org/sssd/ticket/2522 + +Adds a pluggable interface that is able to resolve the IPA group's +external members. At the moment, the request calls the full be_ +interface to make sure all corner cases like id-views are handled +internally. + +Reviewed-by: Sumit Bose +(cherry picked from commit e2d96566aeb881bd89e5c9236d663f6a9a88019a) +(cherry picked from commit 00ee45423f0712b83926c6f8b354a1a18ff741c8) +--- + src/providers/ipa/ipa_id.c | 5 +- + src/providers/ipa/ipa_init.c | 28 +++ + src/providers/ipa/ipa_subdomains.h | 11 ++ + src/providers/ipa/ipa_subdomains_ext_groups.c | 275 ++++++++++++++++++++++++++ + src/providers/ipa/ipa_subdomains_id.c | 1 + + src/providers/ldap/sdap.h | 23 +++ + 6 files changed, 342 insertions(+), 1 deletion(-) + +diff --git a/src/providers/ipa/ipa_id.c b/src/providers/ipa/ipa_id.c +index 27cc2548d8802c81311c6c5bd10a0db4e8930fa1..29e22982c415220c931f0422e10cd06dfa1a195b 100644 +--- a/src/providers/ipa/ipa_id.c ++++ b/src/providers/ipa/ipa_id.c +@@ -405,7 +405,10 @@ static int ipa_initgr_get_overrides_step(struct tevent_req *req) + /* This should never happen, the search filter used to get the list + * of groups includes "uuid=*" + */ +- DEBUG(SSSDBG_OP_FAILURE, "A group with no UUID, error!\n"); ++ DEBUG(SSSDBG_OP_FAILURE, ++ "The group %s has no UUID attribute %s, error!\n", ++ ldb_dn_get_linearized(state->groups[state->group_idx]->dn), ++ state->groups_id_attr); + return EINVAL; + } + +diff --git a/src/providers/ipa/ipa_init.c b/src/providers/ipa/ipa_init.c +index 0e16dd97c78a087256fb77be500c9741484867c5..453e2b25673ac709c9fa3809d35b7885630c8b24 100644 +--- a/src/providers/ipa/ipa_init.c ++++ b/src/providers/ipa/ipa_init.c +@@ -139,6 +139,24 @@ int common_ipa_init(struct be_ctx *bectx) + return EOK; + } + ++static struct sdap_ext_member_ctx * ++ipa_create_ext_members_ctx(TALLOC_CTX *mem_ctx, ++ struct ipa_id_ctx *id_ctx) ++{ ++ struct sdap_ext_member_ctx *ext_ctx = NULL; ++ ++ ext_ctx = talloc_zero(mem_ctx, struct sdap_ext_member_ctx); ++ if (ext_ctx == NULL) { ++ return NULL; ++ } ++ ++ ext_ctx->pvt = id_ctx; ++ ext_ctx->ext_member_resolve_send = ipa_ext_group_member_send; ++ ext_ctx->ext_member_resolve_recv = ipa_ext_group_member_recv; ++ ++ return ext_ctx; ++} ++ + int sssm_ipa_id_init(struct be_ctx *bectx, + struct bet_ops **ops, + void **pvt_data) +@@ -360,6 +378,16 @@ int sssm_ipa_id_init(struct be_ctx *bectx, + "will not work [%d]: %s\n", ret, strerror(ret)); + } + ++ ipa_ctx->sdap_id_ctx->opts->ext_ctx = ipa_create_ext_members_ctx( ++ ipa_ctx->sdap_id_ctx->opts, ++ ipa_ctx); ++ if (ipa_ctx->sdap_id_ctx->opts->ext_ctx == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Unable to set SRV the extrernal group ctx\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ + *ops = &ipa_id_ops; + *pvt_data = ipa_ctx; + ret = EOK; +diff --git a/src/providers/ipa/ipa_subdomains.h b/src/providers/ipa/ipa_subdomains.h +index 0c13f8ed2eeda87237dfb097f532c7137095ddf1..23c3b7e3cd3ee1e0ac1dbcf98dc71a6c2337b835 100644 +--- a/src/providers/ipa/ipa_subdomains.h ++++ b/src/providers/ipa/ipa_subdomains.h +@@ -137,4 +137,15 @@ struct tevent_req *ipa_get_ad_memberships_send(TALLOC_CTX *mem_ctx, + const char *domain); + + errno_t ipa_get_ad_memberships_recv(struct tevent_req *req, int *dp_error_out); ++ ++struct tevent_req *ipa_ext_group_member_send(TALLOC_CTX *mem_ctx, ++ struct tevent_context *ev, ++ const char *ext_member, ++ void *pvt); ++errno_t ipa_ext_group_member_recv(TALLOC_CTX *mem_ctx, ++ struct tevent_req *req, ++ enum sysdb_member_type *_member_type, ++ struct sss_domain_info **_dom, ++ struct sysdb_attrs **_member); ++ + #endif /* _IPA_SUBDOMAINS_H_ */ +diff --git a/src/providers/ipa/ipa_subdomains_ext_groups.c b/src/providers/ipa/ipa_subdomains_ext_groups.c +index d487a58b8adffabe09ff50e31cb750b800b1d252..5dc6d0d6417ec3fb5e7865e4cbaf3c07f4afbd07 100644 +--- a/src/providers/ipa/ipa_subdomains_ext_groups.c ++++ b/src/providers/ipa/ipa_subdomains_ext_groups.c +@@ -923,3 +923,278 @@ static errno_t ipa_add_ad_memberships_recv(struct tevent_req *req, + + return EOK; + } ++ ++static errno_t ++search_user_or_group_by_sid_str(TALLOC_CTX *mem_ctx, ++ struct sss_domain_info *domain, ++ const char *sid_str, ++ enum sysdb_member_type *_member_type, ++ struct ldb_message **_msg) ++{ ++ errno_t ret; ++ struct ldb_message *msg = NULL; ++ const char *attrs[] = { SYSDB_NAME, ++ SYSDB_SID_STR, ++ SYSDB_ORIG_DN, ++ SYSDB_OBJECTCLASS, ++ SYSDB_CACHE_EXPIRE, ++ NULL }; ++ TALLOC_CTX *tmp_ctx = NULL; ++ char *sanitized_sid = NULL; ++ ++ tmp_ctx = talloc_new(NULL); ++ if (tmp_ctx == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n"); ++ return ENOMEM; ++ } ++ ++ /* In theory SID shouldn't contain any special LDAP characters, but let's ++ * be paranoid ++ */ ++ ret = sss_filter_sanitize(tmp_ctx, sid_str, &sanitized_sid); ++ if (ret != EOK) { ++ goto done; ++ } ++ ++ ret = sysdb_search_user_by_sid_str(tmp_ctx, domain, ++ sid_str, attrs, &msg); ++ if (ret == EOK) { ++ *_member_type = SYSDB_MEMBER_USER; ++ } else if (ret == ENOENT) { ++ ret = sysdb_search_group_by_sid_str(tmp_ctx, domain, ++ sid_str, attrs, &msg); ++ if (ret == EOK) { ++ *_member_type = SYSDB_MEMBER_GROUP; ++ } ++ } ++ ++ switch (ret) { ++ case EOK: ++ DEBUG(SSSDBG_TRACE_FUNC, "Found %s in sysdb\n", sid_str); ++ *_msg = talloc_steal(mem_ctx, msg); ++ break; ++ case ENOENT: ++ DEBUG(SSSDBG_TRACE_FUNC, ++ "Could not find %s in sysdb", sid_str); ++ break; ++ default: ++ DEBUG(SSSDBG_OP_FAILURE, ++ "Error looking for %s in sysdb [%d]: %s\n", ++ sid_str, ret, sss_strerror(ret)); ++ break; ++ } ++ ++done: ++ talloc_free(tmp_ctx); ++ return ret; ++} ++ ++static errno_t ++ipa_ext_group_member_check(TALLOC_CTX *mem_ctx, ++ struct ipa_id_ctx *ipa_ctx, ++ struct sss_domain_info *member_dom, ++ const char *ext_member, ++ enum sysdb_member_type *_member_type, ++ struct sysdb_attrs **_member) ++{ ++ TALLOC_CTX *tmp_ctx = NULL; ++ errno_t ret; ++ uint64_t expire; ++ time_t now = time(NULL); ++ struct ldb_message *msg; ++ struct sysdb_attrs **members; ++ ++ tmp_ctx = talloc_new(NULL); ++ if (tmp_ctx == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n"); ++ return ENOMEM; ++ } ++ ++ ret = search_user_or_group_by_sid_str(tmp_ctx, member_dom, ext_member, ++ _member_type, &msg); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "Error looking up sid %s: [%d]: %s\n", ++ ext_member, ret, sss_strerror(ret)); ++ goto done; ++ } ++ ++ ret = sysdb_msg2attrs(tmp_ctx, 1, &msg, &members); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "Could not convert result to sysdb_attrs [%d]: %s\n", ++ ret, sss_strerror(ret)); ++ goto done; ++ } ++ ++ /* Return the member both expired and valid */ ++ *_member = talloc_steal(mem_ctx, members[0]); ++ ++ expire = ldb_msg_find_attr_as_uint64(msg, SYSDB_CACHE_EXPIRE, 0); ++ if (expire != 0 && expire <= now) { ++ DEBUG(SSSDBG_TRACE_FUNC, "%s is expired", ext_member); ++ ret = EAGAIN; ++ goto done; ++ } ++ ++done: ++ talloc_free(tmp_ctx); ++ return ret; ++} ++ ++/* For the IPA external member resolution, we expect a SID as the input. ++ * The _recv() function output is the member and a type (user/group) ++ * since nothing else can be a group member. ++ */ ++struct ipa_ext_member_state { ++ const char *ext_member; ++ struct sss_domain_info *dom; ++ ++ enum sysdb_member_type member_type; ++ struct sysdb_attrs *member; ++}; ++ ++static void ipa_ext_group_member_done(struct tevent_req *subreq); ++ ++struct tevent_req *ipa_ext_group_member_send(TALLOC_CTX *mem_ctx, ++ struct tevent_context *ev, ++ const char *ext_member, ++ void *pvt) ++{ ++ struct ipa_id_ctx *ipa_ctx; ++ struct ipa_ext_member_state *state; ++ struct tevent_req *req; ++ struct tevent_req *subreq; ++ struct be_acct_req *ar; ++ errno_t ret; ++ ++ req = tevent_req_create(mem_ctx, &state, struct ipa_ext_member_state); ++ if (req == NULL) { ++ return NULL; ++ } ++ state->ext_member = ext_member; ++ ++ ipa_ctx = talloc_get_type(pvt, struct ipa_id_ctx); ++ if (ipa_ctx == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Wrong private context!\n"); ++ ret = EINVAL; ++ goto immediate; ++ } ++ ++ state->dom = find_domain_by_sid(ipa_ctx->sdap_id_ctx->be->domain, ++ ext_member); ++ if (state->dom == NULL) { ++ DEBUG(SSSDBG_MINOR_FAILURE, ++ "Cannot find domain of SID [%s]\n", ext_member); ++ ret = ENOENT; ++ goto immediate; ++ } ++ ++ ret = ipa_ext_group_member_check(state, ipa_ctx, state->dom, ext_member, ++ &state->member_type, &state->member); ++ if (ret == EOK) { ++ DEBUG(SSSDBG_TRACE_INTERNAL, ++ "external member %s already cached\n", ext_member); ++ goto immediate; ++ } ++ ++ ret = get_be_acct_req_for_sid(state, ext_member, state->dom->name, &ar); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_MINOR_FAILURE, ++ "Cannot create the account request for [%s]\n", ext_member); ++ goto immediate; ++ } ++ ++ subreq = be_get_account_info_send(state, ev, NULL, ++ ipa_ctx->sdap_id_ctx->be, ar); ++ if (subreq == NULL) { ++ ret = ENOMEM; ++ goto immediate; ++ } ++ tevent_req_set_callback(subreq, ipa_ext_group_member_done, req); ++ ++ return req; ++ ++immediate: ++ if (ret != EOK) { ++ tevent_req_error(req, ret); ++ } else { ++ tevent_req_done(req); ++ } ++ tevent_req_post(req, ev); ++ return req; ++} ++ ++static void ipa_ext_group_member_done(struct tevent_req *subreq) ++{ ++ struct tevent_req *req = tevent_req_callback_data(subreq, ++ struct tevent_req); ++ struct ipa_ext_member_state *state = tevent_req_data(req, ++ struct ipa_ext_member_state); ++ errno_t ret; ++ int err_maj; ++ int err_min; ++ const char *err_msg; ++ struct ldb_message *msg; ++ struct sysdb_attrs **members; ++ ++ ret = be_get_account_info_recv(subreq, state, ++ &err_maj, &err_min, &err_msg); ++ talloc_free(subreq); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "be request failed %d:%d: %s\n", err_maj, err_min, err_msg); ++ tevent_req_error(req, ret); ++ return; ++ } ++ ++ ret = search_user_or_group_by_sid_str(state, ++ state->dom, ++ state->ext_member, ++ &state->member_type, ++ &msg); ++ if (ret != EOK) { ++ DEBUG(ret == ENOENT ? SSSDBG_TRACE_FUNC : SSSDBG_OP_FAILURE, ++ "Could not find %s in sysdb [%d]: %s\n", ++ state->ext_member, ret, sss_strerror(ret)); ++ tevent_req_error(req, ret); ++ return; ++ } ++ ++ ret = sysdb_msg2attrs(state, 1, &msg, &members); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "Could not convert result to sysdb_attrs [%d]: %s\n", ++ ret, sss_strerror(ret)); ++ tevent_req_error(req, ret); ++ return; ++ } ++ ++ state->member = members[0]; ++ tevent_req_done(req); ++} ++ ++errno_t ipa_ext_group_member_recv(TALLOC_CTX *mem_ctx, ++ struct tevent_req *req, ++ enum sysdb_member_type *_member_type, ++ struct sss_domain_info **_dom, ++ struct sysdb_attrs **_member) ++{ ++ struct ipa_ext_member_state *state = tevent_req_data(req, ++ struct ipa_ext_member_state); ++ TEVENT_REQ_RETURN_ON_ERROR(req); ++ ++ if (_member_type != NULL) { ++ *_member_type = state->member_type; ++ } ++ ++ if (_dom) { ++ *_dom = state->dom; ++ } ++ ++ if (_member != NULL) { ++ *_member = talloc_steal(mem_ctx, state->member); ++ } ++ ++ return EOK; ++} +diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c +index 472985d4ab4f785aa9c4af94bf8021829ca1c3c8..70a1b6a12799b5a645bbf69f8cc19c30dcff82c5 100644 +--- a/src/providers/ipa/ipa_subdomains_id.c ++++ b/src/providers/ipa/ipa_subdomains_id.c +@@ -1230,6 +1230,7 @@ static errno_t ipa_get_ad_apply_override_step(struct tevent_req *req) + * attributes set, i.e. where overrides might not have been applied. */ + ret = sysdb_asq_search(state, state->obj_dom, state->obj_msg->dn, + "(&("SYSDB_GC")("SYSDB_GIDNUM"=*)" \ ++ "("SYSDB_POSIX"=TRUE)" \ + "(!("ORIGINALAD_PREFIX SYSDB_GIDNUM"=*))" \ + "(!("ORIGINALAD_PREFIX SYSDB_NAME"=*)))", + SYSDB_INITGR_ATTR, +diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h +index 9dc2e16a0da76246a1f4492cf70e9124edba4a31..e0e05da0c8270a8f131870bc755da862e43783cb 100644 +--- a/src/providers/ldap/sdap.h ++++ b/src/providers/ldap/sdap.h +@@ -423,6 +423,26 @@ struct sdap_domain { + void *pvt; + }; + ++typedef struct tevent_req * ++(*ext_member_send_fn_t)(TALLOC_CTX *mem_ctx, ++ struct tevent_context *ev, ++ const char *ext_member, ++ void *pvt); ++typedef errno_t ++(*ext_member_recv_fn_t)(TALLOC_CTX *mem_ctx, ++ struct tevent_req *req, ++ enum sysdb_member_type *member_type, ++ struct sss_domain_info **_dom, ++ struct sysdb_attrs **_member); ++ ++struct sdap_ext_member_ctx { ++ /* Typically ID context of the external ID provider */ ++ void *pvt; ++ ++ ext_member_send_fn_t ext_member_resolve_send; ++ ext_member_recv_fn_t ext_member_resolve_recv; ++}; ++ + struct sdap_options { + struct dp_option *basic; + struct sdap_attr_map *gen_map; +@@ -435,6 +455,9 @@ struct sdap_options { + /* ID-mapping support */ + struct sdap_idmap_ctx *idmap_ctx; + ++ /* Resolving external members */ ++ struct sdap_ext_member_ctx *ext_ctx; ++ + /* FIXME - should this go to a special struct to avoid mixing with name-service-switch maps? */ + struct sdap_attr_map *sudorule_map; + struct sdap_attr_map *autofs_mobject_map; +-- +2.5.0 + diff --git a/0080-LDAP-Use-the-IPA-provider-interface-to-resolve-exter.patch b/0080-LDAP-Use-the-IPA-provider-interface-to-resolve-exter.patch new file mode 100644 index 0000000..b7d5a64 --- /dev/null +++ b/0080-LDAP-Use-the-IPA-provider-interface-to-resolve-exter.patch @@ -0,0 +1,913 @@ +From 78e95161eb7e27f2160d47580c650930db42b5e8 Mon Sep 17 00:00:00 2001 +From: Jakub Hrozek +Date: Mon, 25 Jan 2016 16:13:03 +0100 +Subject: [PATCH 80/86] LDAP: Use the IPA provider interface to resolve + external group members + +Resolves: + https://fedorahosted.org/sssd/ticket/2522 + +Currently the approach is not optimized for performance, because each +external member is resolved in a full transaction to make sure even ID +views and similar information is processed. + +In future, we should implement https://fedorahosted.org/sssd/ticket/2943 +we will again be able to process all the data in a single transaction. + +Reviewed-by: Sumit Bose +(cherry picked from commit c32266e79f9d4bebd0c31eaa8d6fa26050e7fb3e) +(cherry picked from commit 19194cb18a1cc20f02423861dd831aa5bc3a1003) +--- + src/providers/ldap/sdap_async_groups.c | 49 +- + src/providers/ldap/sdap_async_nested_groups.c | 615 +++++++++++++++++++++++++- + src/providers/ldap/sdap_async_private.h | 16 +- + src/tests/cmocka/test_nested_groups.c | 4 +- + 4 files changed, 656 insertions(+), 28 deletions(-) + +diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c +index 31e0b86a94f1c3969c8fcafe463c591423a835f0..3c274bfccbe65aac9a7ce0fac55839fe05840b79 100644 +--- a/src/providers/ldap/sdap_async_groups.c ++++ b/src/providers/ldap/sdap_async_groups.c +@@ -1758,6 +1758,7 @@ struct sdap_get_groups_state { + struct sysdb_attrs **groups; + size_t count; + size_t check_count; ++ hash_table_t *missing_external; + + hash_table_t *user_hash; + hash_table_t *group_hash; +@@ -2333,6 +2334,8 @@ int sdap_get_groups_recv(struct tevent_req *req, + return EOK; + } + ++static void sdap_nested_ext_done(struct tevent_req *subreq); ++ + static void sdap_nested_done(struct tevent_req *subreq) + { + errno_t ret, tret; +@@ -2348,7 +2351,8 @@ static void sdap_nested_done(struct tevent_req *subreq) + struct sdap_get_groups_state); + + ret = sdap_nested_group_recv(state, subreq, &user_count, &users, +- &group_count, &groups); ++ &group_count, &groups, ++ &state->missing_external); + talloc_zfree(subreq); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Nested group processing failed: [%d][%s]\n", +@@ -2387,8 +2391,25 @@ static void sdap_nested_done(struct tevent_req *subreq) + } + in_transaction = false; + +- /* Processing complete */ +- tevent_req_done(req); ++ if (hash_count(state->missing_external) == 0) { ++ /* No external members. Processing complete */ ++ DEBUG(SSSDBG_TRACE_INTERNAL, "No external members, done"); ++ tevent_req_done(req); ++ return; ++ } ++ ++ /* At the moment, we need to save the direct groups & members in one ++ * transaction and then query the others in a separate requests ++ */ ++ subreq = sdap_nested_group_lookup_external_send(state, state->ev, ++ state->dom, ++ state->opts->ext_ctx, ++ state->missing_external); ++ if (subreq == NULL) { ++ ret = ENOMEM; ++ goto fail; ++ } ++ tevent_req_set_callback(subreq, sdap_nested_ext_done, req); + return; + + fail: +@@ -2401,6 +2422,28 @@ fail: + tevent_req_error(req, ret); + } + ++static void sdap_nested_ext_done(struct tevent_req *subreq) ++{ ++ errno_t ret; ++ struct tevent_req *req = tevent_req_callback_data(subreq, ++ struct tevent_req); ++ struct sdap_get_groups_state *state = tevent_req_data(req, ++ struct sdap_get_groups_state); ++ ++ ret = sdap_nested_group_lookup_external_recv(state, subreq); ++ talloc_free(subreq); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "Cannot resolve external members [%d]: %s\n", ++ ret, sss_strerror(ret)); ++ tevent_req_error(req, ret); ++ return; ++ } ++ ++ tevent_req_done(req); ++ return; ++} ++ + static errno_t sdap_nested_group_populate_users(TALLOC_CTX *mem_ctx, + struct sysdb_ctx *sysdb, + struct sss_domain_info *domain, +diff --git a/src/providers/ldap/sdap_async_nested_groups.c b/src/providers/ldap/sdap_async_nested_groups.c +index 9d715225243d8672850563473bd3938d4cc5db6b..f0d04fa0948abd58470785d07b8d42f3cfeb9eb0 100644 +--- a/src/providers/ldap/sdap_async_nested_groups.c ++++ b/src/providers/ldap/sdap_async_nested_groups.c +@@ -56,6 +56,13 @@ struct sdap_nested_group_member { + const char *group_filter; + }; + ++const size_t external_members_chunk = 16; ++ ++struct sdap_external_missing_member { ++ const char **parent_group_dns; ++ size_t parent_dn_idx; ++}; ++ + struct sdap_nested_group_ctx { + struct sss_domain_info *domain; + struct sdap_options *opts; +@@ -64,6 +71,7 @@ struct sdap_nested_group_ctx { + struct sdap_handle *sh; + hash_table_t *users; + hash_table_t *groups; ++ hash_table_t *missing_external; + bool try_deref; + int deref_treshold; + int max_nesting_level; +@@ -184,37 +192,32 @@ done: + return ret; + } + +-static errno_t sdap_nested_group_hash_entry(hash_table_t *table, +- struct sysdb_attrs *entry, +- const char *table_name) ++static errno_t sdap_nested_group_hash_insert(hash_table_t *table, ++ const char *entry_key, ++ void *entry_value, ++ bool overwrite, ++ const char *table_name) + { + hash_key_t key; + hash_value_t value; +- const char *name = NULL; +- errno_t ret; + int hret; + +- ret = sysdb_attrs_get_string(entry, SYSDB_ORIG_DN, &name); +- if (ret != EOK) { +- return ret; +- } +- + DEBUG(SSSDBG_TRACE_ALL, "Inserting [%s] into hash table [%s]\n", +- name, table_name); ++ entry_key, table_name); + + key.type = HASH_KEY_STRING; +- key.str = talloc_strdup(NULL, name); ++ key.str = talloc_strdup(NULL, entry_key); + if (key.str == NULL) { + return ENOMEM; + } + +- if (hash_has_key(table, &key)) { ++ if (overwrite == false && hash_has_key(table, &key)) { + talloc_free(key.str); + return EEXIST; + } + + value.type = HASH_VALUE_PTR; +- value.ptr = entry; ++ value.ptr = entry_value; + + hret = hash_enter(table, &key, &value); + if (hret != HASH_SUCCESS) { +@@ -228,6 +231,21 @@ static errno_t sdap_nested_group_hash_entry(hash_table_t *table, + return EOK; + } + ++static errno_t sdap_nested_group_hash_entry(hash_table_t *table, ++ struct sysdb_attrs *entry, ++ const char *table_name) ++{ ++ const char *name = NULL; ++ errno_t ret; ++ ++ ret = sysdb_attrs_get_string(entry, SYSDB_ORIG_DN, &name); ++ if (ret != EOK) { ++ return ret; ++ } ++ ++ return sdap_nested_group_hash_insert(table, name, entry, false, table_name); ++} ++ + static errno_t + sdap_nested_group_hash_user(struct sdap_nested_group_ctx *group_ctx, + struct sysdb_attrs *user) +@@ -297,6 +315,76 @@ sdap_nested_group_hash_group(struct sdap_nested_group_ctx *group_ctx, + return sdap_nested_group_hash_entry(group_ctx->groups, group, "groups"); + } + ++static errno_t sdap_nested_group_external_add(hash_table_t *table, ++ const char *ext_member, ++ const char *parent_group_dn) ++{ ++ hash_key_t key; ++ hash_value_t value; ++ int hret; ++ int ret; ++ struct sdap_external_missing_member *ext_mem; ++ ++ key.type = HASH_KEY_STRING; ++ key.str = discard_const(ext_member); ++ ++ DEBUG(SSSDBG_TRACE_ALL, ++ "Inserting external member [%s] into external members hash table\n", ++ ext_member); ++ ++ hret = hash_lookup(table, &key, &value); ++ switch (hret) { ++ case HASH_ERROR_KEY_NOT_FOUND: ++ ext_mem = talloc_zero(table, struct sdap_external_missing_member); ++ if (ext_mem == NULL) { ++ return ENOMEM; ++ } ++ ext_mem->parent_group_dns = talloc_zero_array(ext_mem, ++ const char *, ++ external_members_chunk); ++ if (ext_mem->parent_group_dns == NULL) { ++ talloc_free(ext_mem); ++ return ENOMEM; ++ } ++ ++ ret = sdap_nested_group_hash_insert(table, ext_member, ext_mem, ++ true, "missing external users"); ++ if (ret != EOK) { ++ return ret; ++ } ++ break; ++ ++ case HASH_SUCCESS: ++ ext_mem = talloc_get_type(value.ptr, ++ struct sdap_external_missing_member); ++ if (ext_mem->parent_dn_idx == \ ++ talloc_array_length(ext_mem->parent_group_dns)) { ++ ext_mem->parent_group_dns = talloc_realloc(ext_mem, ++ ext_mem->parent_group_dns, ++ const char *, ++ ext_mem->parent_dn_idx + \ ++ external_members_chunk); ++ if (ext_mem->parent_group_dns == NULL) { ++ talloc_free(ext_mem); ++ return ENOMEM; ++ } ++ } ++ break; ++ default: ++ return EIO; ++ } ++ ++ ext_mem->parent_group_dns[ext_mem->parent_dn_idx] = \ ++ talloc_strdup(ext_mem->parent_group_dns, ++ parent_group_dn); ++ if (ext_mem->parent_group_dns[ext_mem->parent_dn_idx] == NULL) { ++ return ENOMEM; ++ } ++ ext_mem->parent_dn_idx++; ++ ++ return EOK; ++} ++ + static errno_t sdap_nested_group_sysdb_search(struct sss_domain_info *domain, + const char *filter, + bool user) +@@ -478,6 +566,13 @@ sdap_nested_group_split_members(TALLOC_CTX *mem_ctx, + errno_t ret; + int i; + ++ if (members == NULL) { ++ *_missing = NULL; ++ *_num_missing = 0; ++ *_num_groups = 0; ++ return EOK; ++ } ++ + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n"); +@@ -619,6 +714,65 @@ done: + return ret; + } + ++static errno_t ++sdap_nested_group_add_ext_members(TALLOC_CTX *mem_ctx, ++ struct sdap_nested_group_ctx *group_ctx, ++ struct sysdb_attrs *group, ++ struct ldb_message_element *ext_members) ++{ ++ errno_t ret; ++ const char *ext_member_attr; ++ const char *orig_dn; ++ ++ if (ext_members == NULL) { ++ return EOK; ++ } ++ ++ ret = sysdb_attrs_get_string(group, SYSDB_ORIG_DN, &orig_dn); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "A group with no originalDN!?!\n"); ++ return ret; ++ } ++ ++ for (size_t i = 0; i < ext_members->num_values; i++) { ++ ext_member_attr = (const char *) ext_members->values[i].data; ++ ++ ret = sdap_nested_group_external_add(group_ctx->missing_external, ++ ext_member_attr, ++ orig_dn); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Cannot add %s into external members [%d]: %s\n", ++ ext_member_attr, ret, sss_strerror(ret)); ++ return ret; ++ } ++ } ++ ++ return EOK; ++} ++ ++static struct ldb_message_element * ++sdap_nested_group_ext_members(struct sdap_options *opts, ++ struct sysdb_attrs *group) ++{ ++ errno_t ret; ++ struct ldb_message_element *ext_members = NULL; ++ ++ if (opts->ext_ctx == NULL) { ++ return NULL; ++ } ++ ++ ret = sysdb_attrs_get_el_ext(group, ++ opts->group_map[SDAP_AT_GROUP_EXT_MEMBER].sys_name, ++ false, &ext_members); ++ if (ret != EOK && ret != ENOENT) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to retrieve external member list " ++ "[%d]: %s\n", ret, sss_strerror(ret)); ++ } ++ ++ return ext_members; ++} ++ + + struct sdap_nested_group_state { + struct sdap_nested_group_ctx *group_ctx; +@@ -667,6 +821,14 @@ sdap_nested_group_send(TALLOC_CTX *mem_ctx, + goto immediately; + } + ++ ret = sss_hash_create(state->group_ctx, 32, ++ &state->group_ctx->missing_external); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create hash table [%d]: %s\n", ++ ret, strerror(ret)); ++ goto immediately; ++ } ++ + state->group_ctx->try_deref = true; + state->group_ctx->deref_treshold = dp_opt_get_int(opts->basic, + SDAP_DEREF_THRESHOLD); +@@ -760,7 +922,8 @@ errno_t sdap_nested_group_recv(TALLOC_CTX *mem_ctx, + unsigned long *_num_users, + struct sysdb_attrs ***_users, + unsigned long *_num_groups, +- struct sysdb_attrs ***_groups) ++ struct sysdb_attrs ***_groups, ++ hash_table_t **_missing_external) + { + struct sdap_nested_group_state *state = NULL; + struct sysdb_attrs **users = NULL; +@@ -807,6 +970,11 @@ errno_t sdap_nested_group_recv(TALLOC_CTX *mem_ctx, + *_groups = talloc_steal(mem_ctx, groups); + } + ++ if (_missing_external) { ++ *_missing_external = talloc_steal(mem_ctx, ++ state->group_ctx->missing_external); ++ } ++ + return EOK; + } + +@@ -816,6 +984,7 @@ struct sdap_nested_group_process_state { + struct sdap_nested_group_member *missing; + int num_missing_total; + int num_missing_groups; ++ struct ldb_message_element *ext_members; + int nesting_level; + char *group_dn; + bool deref; +@@ -866,13 +1035,16 @@ sdap_nested_group_process_send(TALLOC_CTX *mem_ctx, + + DEBUG(SSSDBG_TRACE_INTERNAL, "About to process group [%s]\n", orig_dn); + +- /* get member list */ ++ /* get member list, both direct and external */ ++ state->ext_members = sdap_nested_group_ext_members(state->group_ctx->opts, ++ group); ++ + ret = sysdb_attrs_get_el_ext(group, group_map[SDAP_AT_GROUP_MEMBER].sys_name, + false, &members); +- if (ret == ENOENT) { +- ret = EOK; /* no members */ ++ if (ret == ENOENT && state->ext_members == NULL) { ++ ret = EOK; /* no members, direct or external */ + goto immediately; +- } else if (ret != EOK) { ++ } else if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to retrieve member list " + "[%d]: %s\n", ret, strerror(ret)); + goto immediately; +@@ -890,14 +1062,31 @@ sdap_nested_group_process_send(TALLOC_CTX *mem_ctx, + goto immediately; + } + +- DEBUG(SSSDBG_TRACE_INTERNAL, "Looking up %d/%d members of group [%s]\n", +- state->num_missing_total, members->num_values, orig_dn); ++ ret = sdap_nested_group_add_ext_members(state, ++ state->group_ctx, ++ group, ++ state->ext_members); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to split external member list " ++ "[%d]: %s\n", ret, sss_strerror(ret)); ++ goto immediately; ++ } + +- if (state->num_missing_total == 0) { ++ if (state->num_missing_total == 0 ++ && hash_count(state->group_ctx->missing_external) == 0) { + ret = EOK; /* we're done */ + goto immediately; + } + ++ /* If there are only indirect members of the group, it's still safe to ++ * proceed and let the direct lookup code just fall through. ++ */ ++ ++ DEBUG(SSSDBG_TRACE_INTERNAL, "Looking up %d/%d members of group [%s]\n", ++ state->num_missing_total, ++ members ? members->num_values : 0, ++ orig_dn); ++ + /* process members */ + if (group_ctx->try_deref + && state->num_missing_total > group_ctx->deref_treshold) { +@@ -2268,3 +2457,385 @@ static errno_t sdap_nested_group_deref_recv(struct tevent_req *req) + + return EOK; + } ++ ++struct sdap_ext_member { ++ struct sdap_external_missing_member *missing_mem; ++ const char *ext_member_attr; ++ ++ enum sysdb_member_type member_type; ++ struct sss_domain_info *dom; ++ struct sysdb_attrs *attrs; ++}; ++ ++struct sdap_nested_group_lookup_external_state { ++ struct tevent_context *ev; ++ struct sdap_ext_member_ctx *ext_ctx; ++ struct sss_domain_info *group_dom; ++ hash_table_t *missing_external; ++ ++ hash_entry_t *entries; ++ unsigned long n_entries; ++ unsigned long eniter; ++ ++ struct sdap_ext_member *ext_members; ++ ++ ext_member_send_fn_t ext_member_resolve_send; ++ ext_member_recv_fn_t ext_member_resolve_recv; ++}; ++ ++static errno_t ++sdap_nested_group_lookup_external_step(struct tevent_req *req); ++static void ++sdap_nested_group_lookup_external_done(struct tevent_req *subreq); ++static errno_t ++sdap_nested_group_lookup_external_link(struct tevent_req *req); ++static errno_t ++sdap_nested_group_lookup_external_link_member( ++ struct sdap_nested_group_lookup_external_state *state, ++ struct sdap_ext_member *member); ++static errno_t ++sdap_nested_group_memberof_dn_by_original_dn( ++ TALLOC_CTX *mem_ctx, ++ struct sss_domain_info *group_dom, ++ const char *original_dn, ++ const char ***_parents); ++ ++struct tevent_req * ++sdap_nested_group_lookup_external_send(TALLOC_CTX *mem_ctx, ++ struct tevent_context *ev, ++ struct sss_domain_info *group_dom, ++ struct sdap_ext_member_ctx *ext_ctx, ++ hash_table_t *missing_external) ++{ ++ struct sdap_nested_group_lookup_external_state *state = NULL; ++ struct tevent_req *req = NULL; ++ errno_t ret; ++ ++ req = tevent_req_create(mem_ctx, &state, ++ struct sdap_nested_group_lookup_external_state); ++ if (req == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); ++ return NULL; ++ } ++ ++ state->ev = ev; ++ state->group_dom = group_dom; ++ state->ext_ctx = ext_ctx; ++ state->missing_external = missing_external; ++ ++ if (state->ext_ctx->ext_member_resolve_send == NULL ++ || state->ext_ctx->ext_member_resolve_recv == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Wrong private context\n"); ++ ret = EINVAL; ++ goto immediately; ++ } ++ ++ ret = hash_entries(state->missing_external, ++ &state->n_entries, &state->entries); ++ if (ret != HASH_SUCCESS) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "hash_entries returned %d\n", ret); ++ ret = EIO; ++ goto immediately; ++ } ++ state->eniter = 0; ++ ++ state->ext_members = talloc_zero_array(state, ++ struct sdap_ext_member, ++ state->n_entries); ++ if (state->ext_members == NULL) { ++ ret = ENOMEM; ++ goto immediately; ++ } ++ ++ ret = sdap_nested_group_lookup_external_step(req); ++ if (ret != EAGAIN) { ++ goto immediately; ++ } ++ ++ return req; ++ ++immediately: ++ if (ret == EOK) { ++ tevent_req_done(req); ++ } else { ++ tevent_req_error(req, ret); ++ } ++ tevent_req_post(req, ev); ++ return req; ++} ++ ++static errno_t ++sdap_nested_group_lookup_external_step(struct tevent_req *req) ++{ ++ struct tevent_req *subreq = NULL; ++ struct sdap_nested_group_lookup_external_state *state = NULL; ++ state = tevent_req_data(req, ++ struct sdap_nested_group_lookup_external_state); ++ ++ subreq = state->ext_ctx->ext_member_resolve_send(state, ++ state->ev, ++ state->entries[state->eniter].key.str, ++ state->ext_ctx->pvt); ++ if (subreq == NULL) { ++ return ENOMEM; ++ } ++ DEBUG(SSSDBG_TRACE_FUNC, "Refreshing member %lu/%lu\n", ++ state->eniter, state->n_entries); ++ tevent_req_set_callback(subreq, ++ sdap_nested_group_lookup_external_done, ++ req); ++ ++ return EAGAIN; ++} ++ ++static void ++sdap_nested_group_lookup_external_done(struct tevent_req *subreq) ++{ ++ errno_t ret; ++ struct tevent_req *req = NULL; ++ struct sdap_nested_group_lookup_external_state *state = NULL; ++ enum sysdb_member_type member_type; ++ struct sysdb_attrs *member; ++ struct sss_domain_info *member_dom; ++ ++ req = tevent_req_callback_data(subreq, struct tevent_req); ++ state = tevent_req_data(req, ++ struct sdap_nested_group_lookup_external_state); ++ ++ ret = state->ext_ctx->ext_member_resolve_recv(state, subreq, ++ &member_type, ++ &member_dom, ++ &member); ++ talloc_free(subreq); ++ if (ret == EOK) { ++ DEBUG(SSSDBG_TRACE_FUNC, "Refreshing member %lu\n", state->eniter); ++ state->ext_members[state->eniter].missing_mem = \ ++ state->entries[state->eniter].value.ptr; ++ state->ext_members[state->eniter].dom = member_dom; ++ ++ state->ext_members[state->eniter].ext_member_attr = \ ++ talloc_steal(state->ext_members, ++ state->entries[state->eniter].key.str); ++ state->ext_members[state->eniter].member_type = member_type; ++ state->ext_members[state->eniter].attrs = \ ++ talloc_steal(state->ext_members, member); ++ } ++ ++ state->eniter++; ++ if (state->eniter >= state->n_entries) { ++ DEBUG(SSSDBG_TRACE_FUNC, "All external members processed\n"); ++ ret = sdap_nested_group_lookup_external_link(req); ++ if (ret != EOK) { ++ tevent_req_error(req, ret); ++ return; ++ } ++ tevent_req_done(req); ++ return; ++ } ++ ++ ret = sdap_nested_group_lookup_external_step(req); ++ if (ret != EOK && ret != EAGAIN) { ++ tevent_req_error(req, ret); ++ return; ++ } ++ ++ return; ++} ++ ++static errno_t ++sdap_nested_group_lookup_external_link(struct tevent_req *req) ++{ ++ errno_t ret, tret; ++ bool in_transaction = false; ++ struct sdap_nested_group_lookup_external_state *state = NULL; ++ state = tevent_req_data(req, ++ struct sdap_nested_group_lookup_external_state); ++ ++ ret = sysdb_transaction_start(state->group_dom->sysdb); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to start transaction\n"); ++ goto fail; ++ } ++ in_transaction = true; ++ ++ ++ for (size_t i = 0; i < state->eniter; i++) { ++ if (state->ext_members[i].attrs == NULL) { ++ DEBUG(SSSDBG_MINOR_FAILURE, "The member %s could not be resolved\n", ++ state->ext_members[i].ext_member_attr); ++ continue; ++ } ++ ++ ret = sdap_nested_group_lookup_external_link_member(state, ++ &state->ext_members[i]); ++ if (ret != EOK) { ++ goto fail; ++ } ++ } ++ ++ ret = sysdb_transaction_commit(state->group_dom->sysdb); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to commit transaction\n"); ++ goto fail; ++ } ++ in_transaction = false; ++ ++ return EOK; ++ ++fail: ++ if (in_transaction) { ++ tret = sysdb_transaction_cancel(state->group_dom->sysdb); ++ if (tret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to cancel transaction\n"); ++ } ++ } ++ return EFAULT; ++} ++ ++static errno_t ++sdap_nested_group_lookup_external_link_member( ++ struct sdap_nested_group_lookup_external_state *state, ++ struct sdap_ext_member *member) ++{ ++ const char *name; ++ int ret; ++ const char **parents = NULL; ++ size_t i; ++ TALLOC_CTX *tmp_ctx; ++ const char *orig_dn; ++ ++ tmp_ctx = talloc_new(state); ++ if (tmp_ctx == NULL) { ++ return ENOMEM; ++ } ++ ++ ret = sysdb_attrs_get_string(member->attrs, SYSDB_NAME, &name); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "No name for a user\n"); ++ goto done; ++ } ++ ++ /* This only works because the groups were saved in a previous ++ * transaction */ ++ for (i=0; i < member->missing_mem->parent_dn_idx; i++) { ++ orig_dn = member->missing_mem->parent_group_dns[i]; ++ DEBUG(SSSDBG_TRACE_INTERNAL, ++ "Linking external members %s from domain %s to parents of %s\n", ++ name, member->dom->name, orig_dn); ++ ret = sdap_nested_group_memberof_dn_by_original_dn(tmp_ctx, ++ state->group_dom, ++ orig_dn, ++ &parents); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_MINOR_FAILURE, ++ "Cannot find parents of %s\n", orig_dn); ++ continue; ++ } ++ ++ /* We don't have to remove the members here, since all members attributes ++ * are always written anew ++ */ ++ ret = sysdb_update_members_dn(member->dom, name, member->member_type, ++ parents, NULL); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Cannot link %s@%s to its parents\n", ++ name, member->dom->name); ++ goto done; ++ } ++ ++ } ++ ++ ret = EOK; ++done: ++ talloc_free(tmp_ctx); ++ return ret; ++} ++ ++static errno_t ++sdap_nested_group_memberof_dn_by_original_dn( ++ TALLOC_CTX *mem_ctx, ++ struct sss_domain_info *group_dom, ++ const char *original_dn, ++ const char ***_parents) ++{ ++ errno_t ret; ++ char *sanitized_dn; ++ char *filter; ++ const char *attrs[] = { SYSDB_NAME, ++ SYSDB_MEMBEROF, ++ NULL }; ++ struct ldb_message **msgs = NULL; ++ size_t count; ++ TALLOC_CTX *tmp_ctx; ++ struct ldb_message_element *memberof; ++ const char **parents; ++ ++ tmp_ctx = talloc_new(mem_ctx); ++ if (tmp_ctx == NULL) { ++ return ENOMEM; ++ } ++ ++ ret = sss_filter_sanitize(tmp_ctx, original_dn, &sanitized_dn); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Cannot sanitize originalDN [%s]\n", original_dn); ++ goto done; ++ } ++ ++ filter = talloc_asprintf(tmp_ctx, "(%s=%s)", SYSDB_ORIG_DN, sanitized_dn); ++ if (filter == NULL) { ++ goto done; ++ } ++ ++ ret = sysdb_search_groups(tmp_ctx, group_dom, filter, attrs, ++ &count, &msgs); ++ if (ret != EOK) { ++ goto done; ++ } ++ ++ if (count != 1) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "More than one entry found by originalDN?\n"); ++ goto done; ++ } ++ ++ memberof = ldb_msg_find_element(msgs[0], SYSDB_MEMBEROF); ++ if (memberof == NULL || memberof->num_values == 0) { ++ DEBUG(SSSDBG_MINOR_FAILURE, ++ "The external group is not a member of any groups\n"); ++ ret = ENOENT; ++ goto done; ++ } ++ ++ parents = talloc_zero_array(tmp_ctx, ++ const char *, ++ memberof->num_values + 1); ++ if (parents == NULL) { ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ for (size_t i = 0; i < memberof->num_values; i++) { ++ parents[i] = talloc_strdup(parents, ++ (const char *) memberof->values[i].data); ++ if (parents[i] == NULL) { ++ ret = ENOMEM; ++ goto done; ++ } ++ } ++ ++ *_parents = talloc_steal(mem_ctx, parents); ++ ret = EOK; ++done: ++ talloc_free(tmp_ctx); ++ return ret; ++} ++ ++errno_t ++sdap_nested_group_lookup_external_recv(TALLOC_CTX *mem_ctx, ++ struct tevent_req *req) ++{ ++ TEVENT_REQ_RETURN_ON_ERROR(req); ++ ++ return EOK; ++} +diff --git a/src/providers/ldap/sdap_async_private.h b/src/providers/ldap/sdap_async_private.h +index db542eaf869efcd53d0937bef3fc6e99cc78b938..9cde6f5dfe0114f797135b4989b9a4bd336a3f27 100644 +--- a/src/providers/ldap/sdap_async_private.h ++++ b/src/providers/ldap/sdap_async_private.h +@@ -130,8 +130,20 @@ errno_t sdap_nested_group_recv(TALLOC_CTX *mem_ctx, + unsigned long *_num_users, + struct sysdb_attrs ***_users, + unsigned long *_num_groups, +- struct sysdb_attrs ***_groups); ++ struct sysdb_attrs ***_groups, ++ hash_table_t **missing_external); + ++struct tevent_req * ++sdap_nested_group_lookup_external_send(TALLOC_CTX *mem_ctx, ++ struct tevent_context *ev, ++ struct sss_domain_info *group_dom, ++ struct sdap_ext_member_ctx *ext_ctx, ++ hash_table_t *missing_external); ++errno_t ++sdap_nested_group_lookup_external_recv(TALLOC_CTX *mem_ctx, ++ struct tevent_req *req); ++ ++/* from sdap_async_initgroups.c */ + errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb, + struct sss_domain_info *domain, + struct sdap_options *opts, +@@ -139,7 +151,7 @@ errno_t sdap_add_incomplete_groups(struct sysdb_ctx *sysdb, + struct sysdb_attrs **ldap_groups, + int ldap_groups_count); + +-/* from sdap_async_nested_groups.c */ ++/* from sdap_ad_groups.c */ + errno_t sdap_check_ad_group_type(struct sss_domain_info *dom, + struct sdap_options *opts, + struct sysdb_attrs *group_attrs, +diff --git a/src/tests/cmocka/test_nested_groups.c b/src/tests/cmocka/test_nested_groups.c +index dc29768c5660d5815d5fab56ee70cc8c9caab330..a3345ef5e087fc90466ce8400dda549fa5d79af8 100644 +--- a/src/tests/cmocka/test_nested_groups.c ++++ b/src/tests/cmocka/test_nested_groups.c +@@ -57,6 +57,7 @@ struct nested_groups_test_ctx { + struct sdap_domain *sdap_domain; + struct sdap_idmap_ctx *idmap_ctx; + struct sdap_id_ctx *sdap_id_ctx; ++ hash_table_t *missing_external; + + struct sysdb_attrs **users; + struct sysdb_attrs **groups; +@@ -110,7 +111,8 @@ static void nested_groups_test_done(struct tevent_req *req) + + ctx->tctx->error = sdap_nested_group_recv(ctx, req, + &ctx->num_users, &ctx->users, +- &ctx->num_groups, &ctx->groups); ++ &ctx->num_groups, &ctx->groups, ++ &ctx->missing_external); + talloc_zfree(req); + + ctx->tctx->done = true; +-- +2.5.0 + diff --git a/0081-build-detect-endianness-at-configure-time.patch b/0081-build-detect-endianness-at-configure-time.patch new file mode 100644 index 0000000..180b917 --- /dev/null +++ b/0081-build-detect-endianness-at-configure-time.patch @@ -0,0 +1,37 @@ +From 245710d26dfa11db998f8a1406b086e76fb8f49b Mon Sep 17 00:00:00 2001 +From: David Disseldorp +Date: Wed, 24 Feb 2016 17:18:00 +0100 +Subject: [PATCH 81/86] build: detect endianness at configure time +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +WORDS_BIGENDIAN, HAVE_BIG_ENDIAN and HAVE_LITTLE_ENDIAN are needed by +Samba. See Samba's byteorder.h header for an example. + +Signed-off-by: David Disseldorp + +Reviewed-by: Lukáš Slebodník +(cherry picked from commit faa16fc9f0c9a02b26497e7cf148a92586144c08) +(cherry picked from commit 15ccbb564d5cc7d6fc8e856811b7ed71c0e220a9) +--- + configure.ac | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/configure.ac b/configure.ac +index 8ef2493c79a144d348200213f0ce1681d0fa3c1f..aebb3c3e9e8d3702295b1b5da28a04c46303af9b 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -76,6 +76,9 @@ AC_CHECK_FUNCS([ utimensat \ + #Check for endian headers + AC_CHECK_HEADERS([endian.h sys/endian.h byteswap.h]) + ++AC_C_BIGENDIAN([AC_DEFINE(HAVE_BIG_ENDIAN, [1], [whether platform is big endian])], ++ [AC_DEFINE(HAVE_LITTLE_ENDIAN, [1], [whether platform is little endian])]) ++ + #Set the NSS library install path + AC_ARG_ENABLE([nsslibdir], [AS_HELP_STRING([--enable-nsslibdir], + [Where to install nss libraries ($libdir)])], +-- +2.5.0 + diff --git a/sssd.spec b/sssd.spec index d6e1152..d86e1ad 100644 --- a/sssd.spec +++ b/sssd.spec @@ -24,7 +24,7 @@ Name: sssd Version: 1.13.3 -Release: 4%{?dist} +Release: 5%{?dist} Group: Applications/System Summary: System Security Services Daemon License: GPLv3+ @@ -83,6 +83,37 @@ Patch0047: 0047-p11-add-gnome-screensaver-to-list-of-allowed-service.patch Patch0048: 0048-IDMAP-Fix-computing-max-id-for-slice-range.patch Patch0049: 0049-IDMAP-New-structure-for-domain-range-params.patch Patch0050: 0050-IDMAP-Add-support-for-automatic-adding-of-ranges.patch +Patch0051: 0051-NSS-do-not-skip-cache-check-for-netgoups.patch +Patch0052: 0052-cache_req-simplify-cache_req_cache_check.patch +Patch0053: 0053-cache_req-do-not-lookup-views-if-possible.patch +Patch0054: 0054-IDMAP-Fix-minor-memory-leak.patch +Patch0055: 0055-CONFIGURE-Replace-obsoleted-macro-AC_PROG_LIBTOOL.patch +Patch0056: 0056-TESTS-Fix-race-condition-in-python-test.patch +Patch0057: 0057-PYTHON-sss_obfuscate-should-work-with-python3.patch +Patch0058: 0058-PYTHON-Fix-pep8-errors-in-sss_obfuscate.patch +Patch0059: 0059-IDMAP-Man-change-for-ldap_idmap_range_size-option.patch +Patch0060: 0060-NSS-Fix-memory-leak-netgroup.patch +Patch0061: 0061-IDMAP-Add-test-to-validate-off-by-one-bug.patch +Patch0062: 0062-SDAP-Add-return-code-ERR_ACCOUNT_LOCKED.patch +Patch0063: 0063-PAM-Pass-account-lockout-status-and-display-message.patch +Patch0064: 0064-PAM-Fix-man-for-pam_account_-expired-locked-_message.patch +Patch0065: 0065-UTIL-Backport-error-code-ERR_ACCOUNT_LOCKED.patch +Patch0066: 0066-sss_idmap-tests-Fix-segmentation-fault.patch +Patch0067: 0067-krb5_child-Warn-if-user-cannot-read-krb5.conf.patch +Patch0068: 0068-Fix-typos-reported-by-lintian.patch +Patch0069: 0069-UTIL-Use-prefix-for-debug-function.patch +Patch0070: 0070-UTIL-Provide-varargs-version-of-debug_fn.patch +Patch0071: 0071-UTIL-Use-sss_vdebug_fn-for-callbacks.patch +Patch0072: 0072-Revert-DEBUG-Preventing-chown_debug_file-if-journald.patch +Patch0073: 0073-DEBUG-Ignore-ENOENT-for-change-owner-of-log-files.patch +Patch0074: 0074-TOOLS-Fix-minor-memory-leak-in-sss_colondb_writeline.patch +Patch0075: 0075-TOOLS-Fix-memory-leak-after-getline-failed.patch +Patch0076: 0076-TOOLS-Add-comments-on-functions-in-colondb.patch +Patch0077: 0077-TEST_TOOLS_COLONDB-Add-tests-for-sss_colondb_.patch +Patch0078: 0078-Add-a-new-option-ldap_group_external_member.patch +Patch0079: 0079-IPA-Add-interface-to-call-into-IPA-provider-from-LDA.patch +Patch0080: 0080-LDAP-Use-the-IPA-provider-interface-to-resolve-exter.patch +Patch0081: 0081-build-detect-endianness-at-configure-time.patch Patch0100: 0100-FO-Don-t-free-rc-allocated-structure.patch Patch0101: 0101-tests-Reduce-failover-code-duplication.patch Patch0102: 0102-FO-Use-refcount-to-keep-track-of-servers-returned-to.patch @@ -1073,6 +1104,12 @@ fi %{_libdir}/%{name}/modules/libwbclient.so %changelog +* Thu Feb 25 2016 Lukas Slebodnik - 1.13.3-5 +- Resolves: rhbz#1310664 - [RFE] IPA: resolve external group memberships of IPA + groups during getgrnam and getgrgid +- Resolves: rhbz#1301303 - sss_obfuscate: SyntaxError: Missing parentheses + in call to 'print' + * Fri Feb 05 2016 Fedora Release Engineering - 1.13.3-4 - Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild