diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-20 15:22:34 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-20 15:22:34 +0000 |
commit | ed95a928eb095f8585bf216a05182a3e30cc9886 (patch) | |
tree | e5039e4c6176a9a4e91f31942e6d2329ff7cc40e /src/providers | |
parent | Adding upstream version 2.9.4. (diff) | |
download | sssd-upstream.tar.xz sssd-upstream.zip |
Adding upstream version 2.9.5.upstream/2.9.5upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r-- | src/providers/ad/ad_gpo.c | 128 | ||||
-rw-r--r-- | src/providers/ad/ad_gpo_child.c | 10 | ||||
-rw-r--r-- | src/providers/ad/ad_subdomains.c | 10 | ||||
-rw-r--r-- | src/providers/be_ptask.c | 10 | ||||
-rw-r--r-- | src/providers/data_provider.h | 1 | ||||
-rw-r--r-- | src/providers/data_provider_fo.c | 14 | ||||
-rw-r--r-- | src/providers/fail_over.c | 10 | ||||
-rw-r--r-- | src/providers/fail_over.h | 3 | ||||
-rw-r--r-- | src/providers/ipa/ipa_auth.c | 13 | ||||
-rw-r--r-- | src/providers/krb5/krb5_auth.c | 66 | ||||
-rw-r--r-- | src/providers/krb5/krb5_child.c | 260 | ||||
-rw-r--r-- | src/providers/krb5/krb5_child_handler.c | 1 | ||||
-rw-r--r-- | src/providers/ldap/ldap_common.h | 1 | ||||
-rw-r--r-- | src/providers/ldap/ldap_id.c | 6 | ||||
-rw-r--r-- | src/providers/ldap/sdap.c | 36 | ||||
-rw-r--r-- | src/providers/ldap/sdap.h | 11 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async.h | 1 | ||||
-rw-r--r-- | src/providers/ldap/sdap_async_initgroups.c | 4 | ||||
-rw-r--r-- | src/providers/ldap/sdap_idmap.c | 4 |
19 files changed, 451 insertions, 138 deletions
diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c index 94959c3..b879b0a 100644 --- a/src/providers/ad/ad_gpo.c +++ b/src/providers/ad/ad_gpo.c @@ -1431,6 +1431,33 @@ ad_gpo_extract_policy_setting(TALLOC_CTX *mem_ctx, return ret; } +static errno_t +add_result_to_hash(hash_table_t *hash, const char *key, char *value) +{ + int hret; + hash_key_t k; + hash_value_t v; + + if (hash == NULL || key == NULL || value == NULL) { + return EINVAL; + } + + k.type = HASH_KEY_CONST_STRING; + k.c_str = key; + + v.type = HASH_VALUE_PTR; + v.ptr = value; + + hret = hash_enter(hash, &k, &v); + if (hret != HASH_SUCCESS) { + DEBUG(SSSDBG_OP_FAILURE, "Failed to add [%s][%s] to hash: [%s].\n", + key, value, hash_error_string(hret)); + return EIO; + } + + return EOK; +} + /* * This function parses the cse-specific (GP_EXT_GUID_SECURITY) filename, * and stores the allow_key and deny_key of all of the gpo_map_types present @@ -1438,6 +1465,7 @@ ad_gpo_extract_policy_setting(TALLOC_CTX *mem_ctx, */ static errno_t ad_gpo_store_policy_settings(struct sss_domain_info *domain, + hash_table_t *allow_maps, hash_table_t *deny_maps, const char *filename) { struct ini_cfgfile *file_ctx = NULL; @@ -1571,14 +1599,14 @@ ad_gpo_store_policy_settings(struct sss_domain_info *domain, goto done; } else if (ret != ENOENT) { const char *value = allow_value ? allow_value : empty_val; - ret = sysdb_gpo_store_gpo_result_setting(domain, - allow_key, - value); + ret = add_result_to_hash(allow_maps, allow_key, + talloc_strdup(allow_maps, value)); if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, - "sysdb_gpo_store_gpo_result_setting failed for key:" - "'%s' value:'%s' [%d][%s]\n", allow_key, allow_value, - ret, sss_strerror(ret)); + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to add key: [%s] " + "value: [%s] to allow maps " + "[%d][%s].\n", + allow_key, value, ret, + sss_strerror(ret)); goto done; } } @@ -1598,14 +1626,14 @@ ad_gpo_store_policy_settings(struct sss_domain_info *domain, goto done; } else if (ret != ENOENT) { const char *value = deny_value ? deny_value : empty_val; - ret = sysdb_gpo_store_gpo_result_setting(domain, - deny_key, - value); + ret = add_result_to_hash(deny_maps, deny_key, + talloc_strdup(deny_maps, value)); if (ret != EOK) { - DEBUG(SSSDBG_CRIT_FAILURE, - "sysdb_gpo_store_gpo_result_setting failed for key:" - "'%s' value:'%s' [%d][%s]\n", deny_key, deny_value, - ret, sss_strerror(ret)); + DEBUG(SSSDBG_CRIT_FAILURE, "Failed to add key: [%s] " + "value: [%s] to deny maps " + "[%d][%s].\n", + deny_key, value, ret, + sss_strerror(ret)); goto done; } } @@ -1902,6 +1930,8 @@ struct ad_gpo_access_state { int num_cse_filtered_gpos; int cse_gpo_index; const char *ad_domain; + hash_table_t *allow_maps; + hash_table_t *deny_maps; }; static void ad_gpo_connect_done(struct tevent_req *subreq); @@ -2023,6 +2053,19 @@ ad_gpo_access_send(TALLOC_CTX *mem_ctx, goto immediately; } + ret = sss_hash_create(state, 0, &state->allow_maps); + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, "Could not create allow maps " + "hash table [%d]: %s\n", ret, sss_strerror(ret)); + goto immediately; + } + + ret = sss_hash_create(state, 0, &state->deny_maps); + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, "Could not create deny maps " + "hash table [%d]: %s\n", ret, sss_strerror(ret)); + goto immediately; + } subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret); if (subreq == NULL) { @@ -2091,6 +2134,7 @@ ad_gpo_connect_done(struct tevent_req *subreq) char *server_uri; LDAPURLDesc *lud; struct sdap_domain *sdom; + struct sdap_search_base **search_bases; req = tevent_req_callback_data(subreq, struct tevent_req); state = tevent_req_data(req, struct ad_gpo_access_state); @@ -2184,9 +2228,20 @@ ad_gpo_connect_done(struct tevent_req *subreq) goto done; } + ret = common_parse_search_base(state, + sdom->naming_context == NULL ? sdom->basedn + : sdom->naming_context, + state->ldb_ctx, "AD_HOSTS", NULL, &search_bases); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Failed to create dedicated search base for host lookups, " + "trying with user search base."); + } + subreq = groups_by_user_send(state, state->ev, state->access_ctx->ad_id_ctx->sdap_id_ctx, sdom, state->conn, + search_bases, state->host_fqdn, BE_FILTER_NAME, NULL, @@ -2701,6 +2756,43 @@ ad_gpo_cse_step(struct tevent_req *req) return EAGAIN; } +static errno_t +store_hash_maps_in_cache(struct sss_domain_info *domain, + hash_table_t *allow_maps, hash_table_t *deny_maps) +{ + int ret; + struct hash_iter_context_t *iter; + hash_entry_t *entry; + size_t c; + hash_table_t *hash_list[] = { allow_maps, deny_maps, NULL}; + + + for (c = 0; hash_list[c] != NULL; c++) { + iter = new_hash_iter_context(hash_list[c]); + if (iter == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "Failed to create hash iterator.\n"); + return EINVAL; + } + + while ((entry = iter->next(iter)) != NULL) { + ret = sysdb_gpo_store_gpo_result_setting(domain, + entry->key.c_str, + entry->value.ptr); + if (ret != EOK) { + free(iter); + DEBUG(SSSDBG_OP_FAILURE, + "sysdb_gpo_store_gpo_result_setting failed for key:" + "[%s] value:[%s] [%d][%s]\n", entry->key.c_str, + (char *) entry->value.ptr, ret, sss_strerror(ret)); + return ret; + } + } + talloc_free(iter); + } + + return EOK; +} + /* * This cse-specific function (GP_EXT_GUID_SECURITY) increments the * cse_gpo_index until the policy settings for all applicable GPOs have been @@ -2742,6 +2834,7 @@ ad_gpo_cse_done(struct tevent_req *subreq) * (as part of the GPO Result object in the sysdb cache). */ ret = ad_gpo_store_policy_settings(state->host_domain, + state->allow_maps, state->deny_maps, cse_filtered_gpo->policy_filename); if (ret != EOK && ret != ENOENT) { DEBUG(SSSDBG_OP_FAILURE, @@ -2755,6 +2848,13 @@ ad_gpo_cse_done(struct tevent_req *subreq) if (ret == EOK) { /* ret is EOK only after all GPO policy files have been downloaded */ + ret = store_hash_maps_in_cache(state->host_domain, + state->allow_maps, state->deny_maps); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "Failed to store evaluated GPO maps " + "[%d][%s].\n", ret, sss_strerror(ret)); + goto done; + } ret = ad_gpo_perform_hbac_processing(state, state->gpo_mode, state->gpo_map_type, diff --git a/src/providers/ad/ad_gpo_child.c b/src/providers/ad/ad_gpo_child.c index 2f2807b..a4f8456 100644 --- a/src/providers/ad/ad_gpo_child.c +++ b/src/providers/ad/ad_gpo_child.c @@ -178,7 +178,8 @@ prepare_response(TALLOC_CTX *mem_ctx, } static void -sssd_krb_get_auth_data_fn(const char * pServer, +sssd_krb_get_auth_data_fn(SMBCCTX *ctx, + const char * pServer, const char * pShare, char * pWorkgroup, int maxLenWorkgroup, @@ -594,9 +595,10 @@ perform_smb_operations(int cached_gpt_version, goto done; } - smbc_setOptionDebugToStderr(smbc_ctx, 1); - smbc_setFunctionAuthData(smbc_ctx, sssd_krb_get_auth_data_fn); - smbc_setOptionUseKerberos(smbc_ctx, 1); + smbc_setOptionDebugToStderr(smbc_ctx, true); + smbc_setFunctionAuthDataWithContext(smbc_ctx, sssd_krb_get_auth_data_fn); + smbc_setOptionUseKerberos(smbc_ctx, true); + smbc_setOptionFallbackAfterKerberos(smbc_ctx, false); /* Initialize the context using the previously specified options */ if (smbc_init_context(smbc_ctx) == NULL) { diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c index a8d1892..d8f3738 100644 --- a/src/providers/ad/ad_subdomains.c +++ b/src/providers/ad/ad_subdomains.c @@ -1395,7 +1395,7 @@ struct ad_get_root_domain_state { static void ad_get_root_domain_done(struct tevent_req *subreq); static void ad_check_root_domain_done(struct tevent_req *subreq); static errno_t -ad_get_root_domain_refresh(struct ad_get_root_domain_state *state); +ad_get_root_domain_refresh(struct ad_get_root_domain_state *state, bool refresh); struct tevent_req * ad_check_domain_send(TALLOC_CTX *mem_ctx, @@ -1582,7 +1582,7 @@ static void ad_get_root_domain_done(struct tevent_req *subreq) return; } - ret = ad_get_root_domain_refresh(state); + ret = ad_get_root_domain_refresh(state, false); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "ad_get_root_domain_refresh() failed.\n"); } @@ -1682,7 +1682,7 @@ static void ad_check_root_domain_done(struct tevent_req *subreq) state->reply_count = 1; - ret = ad_get_root_domain_refresh(state); + ret = ad_get_root_domain_refresh(state, true); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "ad_get_root_domain_refresh() failed.\n"); } @@ -1697,7 +1697,7 @@ done: } static errno_t -ad_get_root_domain_refresh(struct ad_get_root_domain_state *state) +ad_get_root_domain_refresh(struct ad_get_root_domain_state *state, bool refresh) { struct sss_domain_info *root_domain; bool has_changes; @@ -1713,7 +1713,7 @@ ad_get_root_domain_refresh(struct ad_get_root_domain_state *state) goto done; } - if (has_changes) { + if (has_changes || refresh) { ret = ad_subdom_reinit(state->sd_ctx); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "Could not reinitialize subdomains\n"); diff --git a/src/providers/be_ptask.c b/src/providers/be_ptask.c index b351a58..1d6bd9a 100644 --- a/src/providers/be_ptask.c +++ b/src/providers/be_ptask.c @@ -124,7 +124,7 @@ static void be_ptask_execute(struct tevent_context *ev, /* continue */ } - DEBUG(SSSDBG_TRACE_FUNC, "Task [%s]: executing task, timeout %lu " + DEBUG(SSSDBG_TRACE_FUNC, "Task [%s]: executing task, timeout %"SPRItime" " "seconds\n", task->name, task->timeout); task->last_execution = tv.tv_sec; @@ -231,14 +231,14 @@ static void be_ptask_schedule(struct be_ptask *task, if(from & BE_PTASK_SCHEDULE_FROM_NOW) { tv = sss_tevent_timeval_current_ofs_time_t(delay); - DEBUG(SSSDBG_TRACE_FUNC, "Task [%s]: scheduling task %lu seconds " - "from now [%lu]\n", task->name, delay, tv.tv_sec); + DEBUG(SSSDBG_TRACE_FUNC, "Task [%s]: scheduling task %"SPRItime" seconds " + "from now [%"SPRItime"]\n", task->name, delay, tv.tv_sec); } else if (from & BE_PTASK_SCHEDULE_FROM_LAST) { tv = tevent_timeval_set(task->last_execution + delay, 0); - DEBUG(SSSDBG_TRACE_FUNC, "Task [%s]: scheduling task %lu seconds " - "from last execution time [%lu]\n", + DEBUG(SSSDBG_TRACE_FUNC, "Task [%s]: scheduling task %"SPRItime" seconds " + "from last execution time [%"SPRItime"]\n", task->name, delay, tv.tv_sec); } diff --git a/src/providers/data_provider.h b/src/providers/data_provider.h index 36a82b8..def35e4 100644 --- a/src/providers/data_provider.h +++ b/src/providers/data_provider.h @@ -267,6 +267,7 @@ enum dp_res_opts { DP_RES_OPT_RESOLVER_SERVER_TIMEOUT, DP_RES_OPT_RESOLVER_USE_SEARCH_LIST, DP_RES_OPT_DNS_DOMAIN, + DP_RES_OPT_FAILOVER_PRIMARY_TIMEOUT, DP_RES_OPTS /* attrs counter */ }; diff --git a/src/providers/data_provider_fo.c b/src/providers/data_provider_fo.c index b0aed54..c23f92e 100644 --- a/src/providers/data_provider_fo.c +++ b/src/providers/data_provider_fo.c @@ -48,10 +48,20 @@ static int be_fo_get_options(struct be_ctx *ctx, DP_RES_OPT_RESOLVER_TIMEOUT); opts->use_search_list = dp_opt_get_bool(ctx->be_res->opts, DP_RES_OPT_RESOLVER_USE_SEARCH_LIST); + opts->primary_timeout = dp_opt_get_int(ctx->be_res->opts, + DP_RES_OPT_FAILOVER_PRIMARY_TIMEOUT); + opts->retry_timeout = 30; opts->srv_retry_neg_timeout = 15; opts->family_order = ctx->be_res->family_order; + if (opts->primary_timeout <= opts->retry_timeout) { + opts->primary_timeout = opts->retry_timeout + 1; + DEBUG(SSSDBG_CONF_SETTINGS, + "Warning: failover_primary_timeout is too low, using %lu " + "seconds instead\n", opts->primary_timeout); + } + return EOK; } @@ -551,7 +561,7 @@ static void be_resolve_server_done(struct tevent_req *subreq) struct tevent_req); struct be_resolve_server_state *state = tevent_req_data(req, struct be_resolve_server_state); - time_t timeout = fo_get_service_retry_timeout(state->svc->fo_service) + 1; + time_t timeout = fo_get_primary_retry_timeout(state->svc->fo_service); int ret; ret = be_resolve_server_process(subreq, state, &new_subreq); @@ -564,7 +574,6 @@ static void be_resolve_server_done(struct tevent_req *subreq) } if (!fo_is_server_primary(state->srv)) { - /* FIXME: make the timeout configurable */ ret = be_primary_server_timeout_activate(state->ctx, state->ev, state->ctx, state->svc, timeout); @@ -871,6 +880,7 @@ static struct dp_option dp_res_default_opts[] = { { "dns_resolver_server_timeout", DP_OPT_NUMBER, { .number = 1000 }, NULL_NUMBER }, { "dns_resolver_use_search_list", DP_OPT_BOOL, BOOL_TRUE, BOOL_TRUE }, { "dns_discovery_domain", DP_OPT_STRING, NULL_STRING, NULL_STRING }, + { "failover_primary_timeout", DP_OPT_NUMBER, { .number = 31 }, NULL_NUMBER }, DP_OPTION_TERMINATOR }; diff --git a/src/providers/fail_over.c b/src/providers/fail_over.c index 7cb6424..7f94407 100644 --- a/src/providers/fail_over.c +++ b/src/providers/fail_over.c @@ -158,6 +158,7 @@ fo_context_init(TALLOC_CTX *mem_ctx, struct fo_options *opts) ctx->opts->srv_retry_neg_timeout = opts->srv_retry_neg_timeout; ctx->opts->retry_timeout = opts->retry_timeout; + ctx->opts->primary_timeout = opts->primary_timeout; ctx->opts->family_order = opts->family_order; ctx->opts->service_resolv_timeout = opts->service_resolv_timeout; ctx->opts->use_search_list = opts->use_search_list; @@ -1740,6 +1741,15 @@ time_t fo_get_service_retry_timeout(struct fo_service *svc) return svc->ctx->opts->retry_timeout; } +time_t fo_get_primary_retry_timeout(struct fo_service *svc) +{ + if (svc == NULL || svc->ctx == NULL || svc->ctx->opts == NULL) { + return 0; + } + + return svc->ctx->opts->primary_timeout; +} + bool fo_get_use_search_list(struct fo_server *server) { if ( diff --git a/src/providers/fail_over.h b/src/providers/fail_over.h index 36021ad..924a099 100644 --- a/src/providers/fail_over.h +++ b/src/providers/fail_over.h @@ -83,6 +83,7 @@ struct fo_server; struct fo_options { time_t srv_retry_neg_timeout; time_t retry_timeout; + time_t primary_timeout; int service_resolv_timeout; bool use_search_list; enum restrict_family family_order; @@ -211,6 +212,8 @@ int fo_is_srv_lookup(struct fo_server *s); time_t fo_get_service_retry_timeout(struct fo_service *svc); +time_t fo_get_primary_retry_timeout(struct fo_service *svc); + bool fo_get_use_search_list(struct fo_server *server); void fo_reset_services(struct fo_ctx *fo_ctx); diff --git a/src/providers/ipa/ipa_auth.c b/src/providers/ipa/ipa_auth.c index 1d61a10..e5e1bf3 100644 --- a/src/providers/ipa/ipa_auth.c +++ b/src/providers/ipa/ipa_auth.c @@ -258,6 +258,19 @@ static void ipa_pam_auth_handler_krb5_done(struct tevent_req *subreq) if (dp_err != DP_ERR_OK) { goto done; } + if (state->pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM + && state->pd->pam_status == PAM_TRY_AGAIN) { + /* Reset this to fork a new krb5_child in handle_child_send() */ + state->pd->child_pid = 0; + subreq = krb5_auth_queue_send(state, state->ev, state->be_ctx, state->pd, + state->auth_ctx->krb5_auth_ctx); + if (subreq == NULL) { + goto done; + } + + tevent_req_set_callback(subreq, ipa_pam_auth_handler_retry_done, req); + return; + } if (state->pd->cmd == SSS_PAM_AUTHENTICATE && state->pd->pam_status == PAM_CRED_ERR diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c index be34880..9877382 100644 --- a/src/providers/krb5/krb5_auth.c +++ b/src/providers/krb5/krb5_auth.c @@ -36,6 +36,7 @@ #include "util/crypto/sss_crypto.h" #include "util/find_uid.h" #include "util/auth_utils.h" +#include "util/sss_ptr_hash.h" #include "db/sysdb.h" #include "util/sss_utf8.h" #include "util/child_common.h" @@ -427,6 +428,59 @@ static bool is_otp_enabled(struct ldb_message *user_msg) return false; } +/* Closes the write end of waiting krb5_child */ +static errno_t soft_terminate_krb5_child(TALLOC_CTX *mem_ctx, + struct pam_data *pd, + struct krb5_ctx *krb5_ctx) +{ + char *io_key; + struct child_io_fds *io; + TALLOC_CTX *tmp_ctx; + int ret; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + if (pd->child_pid == 0) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Expected waiting krb5_child.\n"); + ret = EINVAL; + goto done; + } + + io_key = talloc_asprintf(tmp_ctx, "%d", pd->child_pid); + if (io_key == NULL) { + ret = ENOMEM; + goto done; + } + + io = sss_ptr_hash_lookup(krb5_ctx->io_table, io_key, + struct child_io_fds); + if (io == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, + "PTR hash lookup failed.\n"); + ret = ENOMEM; + goto done; + } + + if (io->write_to_child_fd != -1) { + ret = close(io->write_to_child_fd); + io->write_to_child_fd = -1; + if (ret != EOK) { + ret = errno; + DEBUG(SSSDBG_CRIT_FAILURE, + "close failed [%d][%s].\n", ret, strerror(ret)); + } + } + + ret = EOK; +done: + talloc_free(tmp_ctx); + return ret; +} + /* krb5_auth request */ struct krb5_auth_state { @@ -532,6 +586,18 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx, ret = EOK; goto done; } + + /* If krb5_child is still running from SSS_PAM_PREAUTH, + * terminate the waiting krb5_child and send the + * CHAUTHTOK_PRELIM request again */ + if (pd->child_pid != 0) { + soft_terminate_krb5_child(state, pd, krb5_ctx); + state->pam_status = PAM_TRY_AGAIN; + state->dp_err = DP_ERR_OK; + ret = EOK; + goto done; + } + break; case SSS_CMD_RENEW: if (authtok_type != SSS_AUTHTOK_TYPE_CCFILE) { diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c index 704f650..494711d 100644 --- a/src/providers/krb5/krb5_child.c +++ b/src/providers/krb5/krb5_child.c @@ -123,7 +123,18 @@ struct krb5_req { }; static krb5_context krb5_error_ctx; -#define KRB5_CHILD_DEBUG(level, error) KRB5_DEBUG(level, krb5_error_ctx, error) + +#define KRB5_CHILD_DEBUG_INT(level, errctx, krb5_error) do { \ + const char *__krb5_error_msg; \ + __krb5_error_msg = sss_krb5_get_error_message(errctx, krb5_error); \ + DEBUG(level, "%d: [%d][%s]\n", __LINE__, krb5_error, __krb5_error_msg); \ + if (level & (SSSDBG_CRIT_FAILURE | SSSDBG_FATAL_FAILURE)) { \ + sss_log(SSS_LOG_ERR, "%s", __krb5_error_msg); \ + } \ + sss_krb5_free_error_message(errctx, __krb5_error_msg); \ +} while(0) + +#define KRB5_CHILD_DEBUG(level, error) KRB5_CHILD_DEBUG_INT(level, krb5_error_ctx, error) static errno_t k5c_attach_otp_info_msg(struct krb5_req *kr); static errno_t k5c_attach_oauth2_info_msg(struct krb5_req *kr, struct sss_idp_oauth2 *data); @@ -734,50 +745,60 @@ static krb5_error_code answer_pkinit(krb5_context ctx, DEBUG(SSSDBG_TRACE_ALL, "Setting pkinit_prompting.\n"); kr->pkinit_prompting = true; - if (kr->pd->cmd == SSS_PAM_AUTHENTICATE - && (sss_authtok_get_type(kr->pd->authtok) + if (kr->pd->cmd == SSS_PAM_AUTHENTICATE) { + if ((sss_authtok_get_type(kr->pd->authtok) == SSS_AUTHTOK_TYPE_SC_PIN || sss_authtok_get_type(kr->pd->authtok) == SSS_AUTHTOK_TYPE_SC_KEYPAD)) { - kerr = sss_authtok_get_sc(kr->pd->authtok, &pin, NULL, - &token_name, NULL, - &module_name, NULL, - NULL, NULL, NULL, NULL); - if (kerr != EOK) { - DEBUG(SSSDBG_OP_FAILURE, - "sss_authtok_get_sc failed.\n"); - goto done; - } + kerr = sss_authtok_get_sc(kr->pd->authtok, &pin, NULL, + &token_name, NULL, + &module_name, NULL, + NULL, NULL, NULL, NULL); + if (kerr != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "sss_authtok_get_sc failed.\n"); + goto done; + } - for (c = 0; chl->identities[c] != NULL; c++) { - if (chl->identities[c]->identity != NULL - && pkinit_identity_matches(chl->identities[c]->identity, - token_name, module_name)) { - break; + for (c = 0; chl->identities[c] != NULL; c++) { + if (chl->identities[c]->identity != NULL + && pkinit_identity_matches(chl->identities[c]->identity, + token_name, module_name)) { + break; + } } - } - if (chl->identities[c] == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, - "No matching identity for [%s][%s] found in pkinit challenge.\n", - token_name, module_name); - kerr = EINVAL; - goto done; - } + if (chl->identities[c] == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, + "No matching identity for [%s][%s] found in pkinit " + "challenge.\n", token_name, module_name); + kerr = EINVAL; + goto done; + } - kerr = krb5_responder_pkinit_set_answer(ctx, rctx, - chl->identities[c]->identity, - pin); - if (kerr != 0) { - DEBUG(SSSDBG_OP_FAILURE, - "krb5_responder_set_answer failed.\n"); - } + kerr = krb5_responder_pkinit_set_answer(ctx, rctx, + chl->identities[c]->identity, + pin); + if (kerr != 0) { + DEBUG(SSSDBG_OP_FAILURE, + "krb5_responder_set_answer failed.\n"); + } - goto done; + goto done; + } else { + DEBUG(SSSDBG_MINOR_FAILURE, + "Unexpected authentication token type [%s]\n", + sss_authtok_type_to_str(sss_authtok_get_type(kr->pd->authtok))); + kerr = EAGAIN; + goto done; + } + } else { + /* We only expect SSS_PAM_PREAUTH here, but also for all other + * commands the graceful solution would be to let the caller + * check other authentication methods as well. */ + kerr = EAGAIN; } - kerr = EOK; - done: krb5_responder_pkinit_challenge_free(ctx, rctx, chl); @@ -903,9 +924,9 @@ static krb5_error_code answer_idp_oauth2(krb5_context kctx, type = sss_authtok_get_type(kr->pd->authtok); if (type != SSS_AUTHTOK_TYPE_OAUTH2) { - DEBUG(SSSDBG_OP_FAILURE, "Unexpected authentication token type [%s]\n", + DEBUG(SSSDBG_MINOR_FAILURE, "Unexpected authentication token type [%s]\n", sss_authtok_type_to_str(type)); - kerr = EINVAL; + kerr = EAGAIN; goto done; } @@ -1130,9 +1151,9 @@ static krb5_error_code answer_passkey(krb5_context kctx, type = sss_authtok_get_type(kr->pd->authtok); if (type != SSS_AUTHTOK_TYPE_PASSKEY_REPLY) { - DEBUG(SSSDBG_OP_FAILURE, "Unexpected authentication token type [%s]\n", + DEBUG(SSSDBG_MINOR_FAILURE, "Unexpected authentication token type [%s]\n", sss_authtok_type_to_str(type)); - kerr = EINVAL; + kerr = EAGAIN; goto done; } @@ -1186,6 +1207,44 @@ done: #endif /* BUILD_PASSKEY */ } +static krb5_error_code answer_password(krb5_context kctx, + struct krb5_req *kr, + krb5_responder_context rctx) +{ + krb5_error_code kerr; + int ret; + const char *pwd; + + kr->password_prompting = true; + + if ((kr->pd->cmd == SSS_PAM_AUTHENTICATE + || kr->pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM + || kr->pd->cmd == SSS_PAM_CHAUTHTOK) + && sss_authtok_get_type(kr->pd->authtok) + == SSS_AUTHTOK_TYPE_PASSWORD) { + ret = sss_authtok_get_password(kr->pd->authtok, &pwd, NULL); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "sss_authtok_get_password failed.\n"); + return ret; + } + + kerr = krb5_responder_set_answer(kctx, rctx, + KRB5_RESPONDER_QUESTION_PASSWORD, + pwd); + if (kerr != 0) { + DEBUG(SSSDBG_OP_FAILURE, + "krb5_responder_set_answer failed.\n"); + } + + return kerr; + } + + /* For SSS_PAM_PREAUTH and the other remaining commands the caller should + * continue to iterate over the available authentication methods. */ + return EAGAIN; +} + static krb5_error_code sss_krb5_responder(krb5_context ctx, void *data, krb5_responder_context rctx) @@ -1193,9 +1252,7 @@ static krb5_error_code sss_krb5_responder(krb5_context ctx, struct krb5_req *kr = talloc_get_type(data, struct krb5_req); const char * const *question_list; size_t c; - const char *pwd; - int ret; - krb5_error_code kerr; + krb5_error_code kerr = EINVAL; if (kr == NULL) { return EINVAL; @@ -1207,48 +1264,76 @@ static krb5_error_code sss_krb5_responder(krb5_context ctx, for (c = 0; question_list[c] != NULL; c++) { DEBUG(SSSDBG_TRACE_ALL, "Got question [%s].\n", question_list[c]); + /* It is expected that the answer_*() functions only return EOK + * (success) if the authentication was successful, i.e. during + * SSS_PAM_AUTHENTICATE. In all other cases, e.g. during + * SSS_PAM_PREAUTH either EAGAIN should be returned to indicate + * that the other available authentication methods should be + * checked as well. Or some other error code to indicate a fatal + * error where no other methods should be tried. + * Especially if setting the answer failed neither EOK nor EAGAIN + * should be returned. */ if (strcmp(question_list[c], KRB5_RESPONDER_QUESTION_PASSWORD) == 0) { - kr->password_prompting = true; - - if ((kr->pd->cmd == SSS_PAM_AUTHENTICATE - || kr->pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM - || kr->pd->cmd == SSS_PAM_CHAUTHTOK) - && sss_authtok_get_type(kr->pd->authtok) - == SSS_AUTHTOK_TYPE_PASSWORD) { - ret = sss_authtok_get_password(kr->pd->authtok, &pwd, NULL); - if (ret != EOK) { - DEBUG(SSSDBG_OP_FAILURE, - "sss_authtok_get_password failed.\n"); - return ret; - } - - kerr = krb5_responder_set_answer(ctx, rctx, - KRB5_RESPONDER_QUESTION_PASSWORD, - pwd); - if (kerr != 0) { - DEBUG(SSSDBG_OP_FAILURE, - "krb5_responder_set_answer failed.\n"); - } - - return kerr; - } + kerr = answer_password(ctx, kr, rctx); } else if (strcmp(question_list[c], KRB5_RESPONDER_QUESTION_PKINIT) == 0 && (sss_authtok_get_type(kr->pd->authtok) == SSS_AUTHTOK_TYPE_SC_PIN || sss_authtok_get_type(kr->pd->authtok) == SSS_AUTHTOK_TYPE_SC_KEYPAD)) { - return answer_pkinit(ctx, kr, rctx); + kerr = answer_pkinit(ctx, kr, rctx); } else if (strcmp(question_list[c], SSSD_IDP_OAUTH2_QUESTION) == 0) { - return answer_idp_oauth2(ctx, kr, rctx); + kerr = answer_idp_oauth2(ctx, kr, rctx); } else if (strcmp(question_list[c], SSSD_PASSKEY_QUESTION) == 0) { - return answer_passkey(ctx, kr, rctx); + /* Skip answer_passkey for expired password changes, e.g. user with auth types + * passkey AND password set */ + if (kr->pd->cmd == SSS_PAM_CHAUTHTOK_PRELIM || kr->pd->cmd == SSS_PAM_CHAUTHTOK) { + continue; + } + kerr = answer_passkey(ctx, kr, rctx); + } else if (strcmp(question_list[c], KRB5_RESPONDER_QUESTION_OTP) == 0) { + kerr = answer_otp(ctx, kr, rctx); + } else { + DEBUG(SSSDBG_MINOR_FAILURE, "Unknown question type [%s]\n", question_list[c]); + kerr = EINVAL; + } + + /* Continue to the next question when the given authtype cannot be + * handled by the answer_* function. This allows fallback between auth + * types, such as passkey -> password. */ + if (kerr == EAGAIN) { + /* During pre-auth iterating over all authentication methods + * is expected and no message will be displayed. */ + if (kr->pd->cmd == SSS_PAM_AUTHENTICATE) { + DEBUG(SSSDBG_TRACE_ALL, + "Auth type [%s] could not be handled by answer " + "function, continuing to next question.\n", + question_list[c]); + } + continue; + } else { + return kerr; } } + } else { + kerr = answer_password(ctx, kr, rctx); } - return answer_otp(ctx, kr, rctx); + /* During SSS_PAM_PREAUTH 'EAGAIN' is expected because we will run + * through all offered authentication methods and all are expect to return + * 'EAGAIN' in the positive case to indicate that the other methods should + * be checked as well. If all methods are checked we are done and should + * return success. + * In the other steps, especially SSS_PAM_AUTHENTICATE, having 'EAGAIN' at + * this stage would mean that no method feels responsible for the provided + * credentials i.e. authentication failed and we should return an error. + */ + if (kr->pd->cmd == SSS_PAM_PREAUTH) { + return kerr == EAGAIN ? 0 : kerr; + } else { + return kerr; + } } #endif /* HAVE_KRB5_GET_INIT_CREDS_OPT_SET_RESPONDER */ @@ -1270,13 +1355,14 @@ static krb5_error_code sss_krb5_prompter(krb5_context context, void *data, int ret; size_t c; struct krb5_req *kr = talloc_get_type(data, struct krb5_req); + const char *err_msg; if (kr == NULL) { return EINVAL; } DEBUG(SSSDBG_TRACE_ALL, - "sss_krb5_prompter name [%s] banner [%s] num_prompts [%d] EINVAL.\n", + "sss_krb5_prompter name [%s] banner [%s] num_prompts [%d].\n", name, banner, num_prompts); if (num_prompts != 0) { @@ -1285,7 +1371,12 @@ static krb5_error_code sss_krb5_prompter(krb5_context context, void *data, prompts[c].prompt); } - DEBUG(SSSDBG_FUNC_DATA, "Prompter interface isn't used for password prompts by SSSD.\n"); + err_msg = krb5_get_error_message(context, KRB5_LIBOS_CANTREADPWD); + DEBUG(SSSDBG_FUNC_DATA, + "Prompter interface isn't used for prompting by SSSD." + "Returning the expected error [%ld/%s].\n", + KRB5_LIBOS_CANTREADPWD, err_msg); + krb5_free_error_message(context, err_msg); return KRB5_LIBOS_CANTREADPWD; } @@ -1314,7 +1405,7 @@ static krb5_error_code create_empty_cred(krb5_context ctx, krb5_principal princ, krb5_creds *cred = NULL; krb5_data *krb5_realm; - cred = calloc(sizeof(krb5_creds), 1); + cred = calloc(1, sizeof(krb5_creds)); if (cred == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "calloc failed.\n"); return ENOMEM; @@ -2158,19 +2249,25 @@ sss_krb5_get_init_creds_password(krb5_context context, krb5_creds *creds, { krb5_error_code kerr; krb5_init_creds_context init_cred_ctx = NULL; + int log_level = SSSDBG_MINOR_FAILURE; + struct krb5_req *kr = talloc_get_type(data, struct krb5_req); + + if (kr->pd->cmd != SSS_PAM_PREAUTH) { + log_level = SSSDBG_OP_FAILURE; + } kerr = krb5_init_creds_init(context, client, prompter, data, start_time, k5_gic_options, &init_cred_ctx); if (kerr != 0) { - KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr); + KRB5_CHILD_DEBUG(log_level, kerr); goto done; } if (password != NULL) { kerr = krb5_init_creds_set_password(context, init_cred_ctx, password); if (kerr != 0) { - KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr); + KRB5_CHILD_DEBUG(log_level, kerr); goto done; } } @@ -2179,7 +2276,7 @@ sss_krb5_get_init_creds_password(krb5_context context, krb5_creds *creds, kerr = krb5_init_creds_set_service(context, init_cred_ctx, in_tkt_service); if (kerr != 0) { - KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr); + KRB5_CHILD_DEBUG(log_level, kerr); goto done; } } @@ -2190,7 +2287,7 @@ sss_krb5_get_init_creds_password(krb5_context context, krb5_creds *creds, } if (kerr != 0) { - KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr); + KRB5_CHILD_DEBUG(log_level, kerr); goto done; } @@ -2391,12 +2488,12 @@ static errno_t map_krb5_error(krb5_error_code kerr) { /* just pass SSSD's internal error codes */ if (kerr > 0 && IS_SSSD_ERROR(kerr)) { - DEBUG(SSSDBG_CRIT_FAILURE, "[%d][%s].\n", kerr, sss_strerror(kerr)); + DEBUG(SSSDBG_OP_FAILURE, "[%d][%s].\n", kerr, sss_strerror(kerr)); return kerr; } if (kerr != 0) { - KRB5_CHILD_DEBUG(SSSDBG_CRIT_FAILURE, kerr); + KRB5_CHILD_DEBUG(SSSDBG_OP_FAILURE, kerr); } switch (kerr) { @@ -2748,8 +2845,9 @@ static errno_t tgt_req_child(struct krb5_req *kr) * should now know which authentication methods are available to * update the password. */ DEBUG(SSSDBG_TRACE_FUNC, - "krb5_get_init_creds_password returned [%d] during pre-auth, " - "ignored.\n", kerr); + "krb5_get_init_creds_password returned [%d] while collecting " + "available authentication types, errors are expected " + "and ignored.\n", kerr); ret = pam_add_prompting(kr); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_prompting failed.\n"); diff --git a/src/providers/krb5/krb5_child_handler.c b/src/providers/krb5/krb5_child_handler.c index 54088e4..17befd4 100644 --- a/src/providers/krb5/krb5_child_handler.c +++ b/src/providers/krb5/krb5_child_handler.c @@ -1020,3 +1020,4 @@ parse_krb5_child_response(TALLOC_CTX *mem_ctx, uint8_t *buf, ssize_t len, *_res = res; return EOK; } + diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h index 7159d63..2c984ef 100644 --- a/src/providers/ldap/ldap_common.h +++ b/src/providers/ldap/ldap_common.h @@ -304,6 +304,7 @@ struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx, struct sdap_id_ctx *ctx, struct sdap_domain *sdom, struct sdap_id_conn_ctx *conn, + struct sdap_search_base **search_bases, const char *filter_value, int filter_type, const char *extra_value, diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c index da54816..b3ea233 100644 --- a/src/providers/ldap/ldap_id.c +++ b/src/providers/ldap/ldap_id.c @@ -1139,6 +1139,7 @@ struct groups_by_user_state { struct sdap_id_op *op; struct sysdb_ctx *sysdb; struct sss_domain_info *domain; + struct sdap_search_base **search_bases; const char *filter_value; int filter_type; @@ -1160,6 +1161,7 @@ struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx, struct sdap_id_ctx *ctx, struct sdap_domain *sdom, struct sdap_id_conn_ctx *conn, + struct sdap_search_base **search_bases, const char *filter_value, int filter_type, const char *extra_value, @@ -1192,6 +1194,7 @@ struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx, state->extra_value = extra_value; state->domain = sdom->dom; state->sysdb = sdom->dom->sysdb; + state->search_bases = search_bases; if (state->domain->type == DOM_TYPE_APPLICATION || set_non_posix) { state->non_posix = true; @@ -1254,6 +1257,7 @@ static void groups_by_user_connect_done(struct tevent_req *subreq) sdap_id_op_handle(state->op), state->ctx, state->conn, + state->search_bases, state->filter_value, state->filter_type, state->extra_value, @@ -1449,7 +1453,7 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx, } subreq = groups_by_user_send(state, be_ctx->ev, id_ctx, - sdom, conn, + sdom, conn, NULL, ar->filter_value, ar->filter_type, ar->extra_value, diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c index f5637c5..956eba9 100644 --- a/src/providers/ldap/sdap.c +++ b/src/providers/ldap/sdap.c @@ -1252,19 +1252,10 @@ errno_t sdap_set_config_options_with_rootdse(struct sysdb_attrs *rootdse, struct sdap_domain *sdom) { int ret; - char *naming_context = NULL; - if (!sdom->search_bases - || !sdom->user_search_bases - || !sdom->group_search_bases - || !sdom->netgroup_search_bases - || !sdom->host_search_bases - || !sdom->sudo_search_bases - || !sdom->iphost_search_bases - || !sdom->ipnetwork_search_bases - || !sdom->autofs_search_bases) { - naming_context = get_naming_context(opts->basic, rootdse); - if (naming_context == NULL) { + if (!sdom->naming_context) { + sdom->naming_context = get_naming_context(sdom, rootdse); + if (sdom->naming_context == NULL) { DEBUG(SSSDBG_CRIT_FAILURE, "get_naming_context failed.\n"); /* This has to be non-fatal, since some servers offer @@ -1280,7 +1271,7 @@ errno_t sdap_set_config_options_with_rootdse(struct sysdb_attrs *rootdse, if (!sdom->search_bases) { ret = sdap_set_search_base(opts, sdom, SDAP_SEARCH_BASE, - naming_context); + sdom->naming_context); if (ret != EOK) goto done; } @@ -1288,7 +1279,7 @@ errno_t sdap_set_config_options_with_rootdse(struct sysdb_attrs *rootdse, if (!sdom->user_search_bases) { ret = sdap_set_search_base(opts, sdom, SDAP_USER_SEARCH_BASE, - naming_context); + sdom->naming_context); if (ret != EOK) goto done; } @@ -1296,7 +1287,7 @@ errno_t sdap_set_config_options_with_rootdse(struct sysdb_attrs *rootdse, if (!sdom->group_search_bases) { ret = sdap_set_search_base(opts, sdom, SDAP_GROUP_SEARCH_BASE, - naming_context); + sdom->naming_context); if (ret != EOK) goto done; } @@ -1304,7 +1295,7 @@ errno_t sdap_set_config_options_with_rootdse(struct sysdb_attrs *rootdse, if (!sdom->netgroup_search_bases) { ret = sdap_set_search_base(opts, sdom, SDAP_NETGROUP_SEARCH_BASE, - naming_context); + sdom->naming_context); if (ret != EOK) goto done; } @@ -1312,7 +1303,7 @@ errno_t sdap_set_config_options_with_rootdse(struct sysdb_attrs *rootdse, if (!sdom->host_search_bases) { ret = sdap_set_search_base(opts, sdom, SDAP_HOST_SEARCH_BASE, - naming_context); + sdom->naming_context); if (ret != EOK) goto done; } @@ -1320,7 +1311,7 @@ errno_t sdap_set_config_options_with_rootdse(struct sysdb_attrs *rootdse, if (!sdom->sudo_search_bases) { ret = sdap_set_search_base(opts, sdom, SDAP_SUDO_SEARCH_BASE, - naming_context); + sdom->naming_context); if (ret != EOK) goto done; } @@ -1328,7 +1319,7 @@ errno_t sdap_set_config_options_with_rootdse(struct sysdb_attrs *rootdse, if (!sdom->service_search_bases) { ret = sdap_set_search_base(opts, sdom, SDAP_SERVICE_SEARCH_BASE, - naming_context); + sdom->naming_context); if (ret != EOK) goto done; } @@ -1336,7 +1327,7 @@ errno_t sdap_set_config_options_with_rootdse(struct sysdb_attrs *rootdse, if (!sdom->autofs_search_bases) { ret = sdap_set_search_base(opts, sdom, SDAP_AUTOFS_SEARCH_BASE, - naming_context); + sdom->naming_context); if (ret != EOK) goto done; } @@ -1344,7 +1335,7 @@ errno_t sdap_set_config_options_with_rootdse(struct sysdb_attrs *rootdse, if (!sdom->iphost_search_bases) { ret = sdap_set_search_base(opts, sdom, SDAP_IPHOST_SEARCH_BASE, - naming_context); + sdom->naming_context); if (ret != EOK) goto done; } @@ -1352,14 +1343,13 @@ errno_t sdap_set_config_options_with_rootdse(struct sysdb_attrs *rootdse, if (!sdom->ipnetwork_search_bases) { ret = sdap_set_search_base(opts, sdom, SDAP_IPNETWORK_SEARCH_BASE, - naming_context); + sdom->naming_context); if (ret != EOK) goto done; } ret = EOK; done: - talloc_free(naming_context); return ret; } diff --git a/src/providers/ldap/sdap.h b/src/providers/ldap/sdap.h index 161bc5c..103d50e 100644 --- a/src/providers/ldap/sdap.h +++ b/src/providers/ldap/sdap.h @@ -454,6 +454,17 @@ struct sdap_domain { char *basedn; + /* The naming_context could be a more reliable source than basedn for the + * actual base DN because basedn is set very early from the domain name + * given in sssd.conf. Although it is recommended to use the fully + * qualified DNS domain name here it is not required. As a result basedn + * might not reflect the actual based DN of the LDAP server. Also pure + * LDAP server (i.e. not AD or FreeIPA) might use different schemes to set + * the base DN which will not be based on the DNS domain of the LDAP + * server. naming_context might be NULL even after connection to an LDAP + * server. */ + char *naming_context; + struct sdap_search_base **search_bases; struct sdap_search_base **user_search_bases; struct sdap_search_base **group_search_bases; diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h index 5458d21..89245f4 100644 --- a/src/providers/ldap/sdap_async.h +++ b/src/providers/ldap/sdap_async.h @@ -158,6 +158,7 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, struct sdap_handle *sh, struct sdap_id_ctx *id_ctx, struct sdap_id_conn_ctx *conn, + struct sdap_search_base **search_bases, const char *name, int filter_type, const char *extra_value, diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c index 97be594..fb3d8fe 100644 --- a/src/providers/ldap/sdap_async_initgroups.c +++ b/src/providers/ldap/sdap_async_initgroups.c @@ -2732,6 +2732,7 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, struct sdap_handle *sh, struct sdap_id_ctx *id_ctx, struct sdap_id_conn_ctx *conn, + struct sdap_search_base **search_bases, const char *filter_value, int filter_type, const char *extra_value, @@ -2764,7 +2765,8 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, state->orig_user = NULL; state->timeout = dp_opt_get_int(state->opts->basic, SDAP_SEARCH_TIMEOUT); state->user_base_iter = 0; - state->user_search_bases = sdom->user_search_bases; + state->user_search_bases = (search_bases == NULL) ? sdom->user_search_bases + : search_bases; if (!state->user_search_bases) { DEBUG(SSSDBG_CRIT_FAILURE, "Initgroups lookup request without a user search base\n"); diff --git a/src/providers/ldap/sdap_idmap.c b/src/providers/ldap/sdap_idmap.c index 3795ed6..e982308 100644 --- a/src/providers/ldap/sdap_idmap.c +++ b/src/providers/ldap/sdap_idmap.c @@ -506,8 +506,8 @@ sdap_idmap_sid_to_unix(struct sdap_idmap_ctx *idmap_ctx, (uint32_t *)id); if (err != IDMAP_SUCCESS) { DEBUG(SSSDBG_MINOR_FAILURE, - "Could not convert objectSID [%s] to a UNIX ID\n", - sid_str); + "Could not convert objectSID [%s] to a UNIX ID [%d] [%s]\n", + sid_str, err, idmap_error_string(err)); ret = EIO; goto done; } |