summaryrefslogtreecommitdiffstats
path: root/src/providers
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-20 15:22:34 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-20 15:22:34 +0000
commited95a928eb095f8585bf216a05182a3e30cc9886 (patch)
treee5039e4c6176a9a4e91f31942e6d2329ff7cc40e /src/providers
parentAdding upstream version 2.9.4. (diff)
downloadsssd-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.c128
-rw-r--r--src/providers/ad/ad_gpo_child.c10
-rw-r--r--src/providers/ad/ad_subdomains.c10
-rw-r--r--src/providers/be_ptask.c10
-rw-r--r--src/providers/data_provider.h1
-rw-r--r--src/providers/data_provider_fo.c14
-rw-r--r--src/providers/fail_over.c10
-rw-r--r--src/providers/fail_over.h3
-rw-r--r--src/providers/ipa/ipa_auth.c13
-rw-r--r--src/providers/krb5/krb5_auth.c66
-rw-r--r--src/providers/krb5/krb5_child.c260
-rw-r--r--src/providers/krb5/krb5_child_handler.c1
-rw-r--r--src/providers/ldap/ldap_common.h1
-rw-r--r--src/providers/ldap/ldap_id.c6
-rw-r--r--src/providers/ldap/sdap.c36
-rw-r--r--src/providers/ldap/sdap.h11
-rw-r--r--src/providers/ldap/sdap_async.h1
-rw-r--r--src/providers/ldap/sdap_async_initgroups.c4
-rw-r--r--src/providers/ldap/sdap_idmap.c4
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;
}