diff --git a/SOURCES/0009-kcm-decode-base64-encoded-secret-on-upgrade-path.patch b/SOURCES/0009-kcm-decode-base64-encoded-secret-on-upgrade-path.patch new file mode 100644 index 0000000..032f1c4 --- /dev/null +++ b/SOURCES/0009-kcm-decode-base64-encoded-secret-on-upgrade-path.patch @@ -0,0 +1,43 @@ +From 18b98836ef8e337992f0ecb239a32b9c3cedb750 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Wed, 9 Dec 2020 14:07:22 +0100 +Subject: [PATCH] kcm: decode base64 encoded secret on upgrade path + +Previous unefficient code encoded the secret multiple times: + secret -> base64 -> masterkey -> base64 + +To allow smooth upgrade for already existant ccache we need to also decode +the secret if it is still in the old format (type == simple). Otherwise +users are not able to log in. + +Resolves: https://github.com/SSSD/sssd/issues/5349 + +Reviewed-by: Alexey Tikhonov +--- + src/responder/kcm/kcmsrv_ccache_secdb.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/src/responder/kcm/kcmsrv_ccache_secdb.c b/src/responder/kcm/kcmsrv_ccache_secdb.c +index 726711ac4..ea5c8f9ee 100644 +--- a/src/responder/kcm/kcmsrv_ccache_secdb.c ++++ b/src/responder/kcm/kcmsrv_ccache_secdb.c +@@ -59,6 +59,16 @@ static errno_t sec_get(TALLOC_CTX *mem_ctx, + goto done; + } + ++ if (strcmp(datatype, "simple") == 0) { ++ /* The secret is stored in b64 encoding, we need to decode it first. */ ++ data = sss_base64_decode(tmp_ctx, (const char*)data, &len); ++ if (data == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Cannot decode secret from base64\n"); ++ ret = EIO; ++ goto done; ++ } ++ } ++ + buf = sss_iobuf_init_steal(tmp_ctx, data, len); + if (buf == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Cannot init the iobuf\n"); +-- +2.21.3 + diff --git a/SOURCES/0010-nss-check-if-groups-are-filtered-during-initgroups.patch b/SOURCES/0010-nss-check-if-groups-are-filtered-during-initgroups.patch new file mode 100644 index 0000000..8e76f9a --- /dev/null +++ b/SOURCES/0010-nss-check-if-groups-are-filtered-during-initgroups.patch @@ -0,0 +1,112 @@ +From c87b2208b9a58c12eeceb5b8ccf9c34dcd835b8d Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Tue, 17 Nov 2020 12:59:23 +0100 +Subject: [PATCH] nss: check if groups are filtered during initgroups +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +If groups are filtered, i.e. SSSD should not handle them, they should +not appear in the group list returned by an initgroups request. + +Resolves: https://github.com/SSSD/sssd/issues/5403 + +Reviewed-by: Pavel Březina +--- + src/responder/nss/nss_protocol_grent.c | 35 ++++++++++++++++++++++++++ + src/tests/intg/test_ldap.py | 12 +++++++++ + 2 files changed, 47 insertions(+) + +diff --git a/src/responder/nss/nss_protocol_grent.c b/src/responder/nss/nss_protocol_grent.c +index 8f1d3fe81..135b392f7 100644 +--- a/src/responder/nss/nss_protocol_grent.c ++++ b/src/responder/nss/nss_protocol_grent.c +@@ -326,6 +326,34 @@ done: + return EOK; + } + ++static bool is_group_filtered(struct sss_nc_ctx *ncache, ++ struct sss_domain_info *domain, ++ const char *grp_name, gid_t gid) ++{ ++ int ret; ++ ++ if (grp_name == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Group with gid [%"SPRIgid"] has no name, this should never " ++ "happen, trying to continue without.\n", gid); ++ } else { ++ ret = sss_ncache_check_group(ncache, domain, grp_name); ++ if (ret == EEXIST) { ++ DEBUG(SSSDBG_TRACE_FUNC, "Group [%s] is filtered out! " ++ "(negative cache)", grp_name); ++ return true; ++ } ++ } ++ ret = sss_ncache_check_gid(ncache, domain, gid); ++ if (ret == EEXIST) { ++ DEBUG(SSSDBG_TRACE_FUNC, "Group [%"SPRIgid"] is filtered out! " ++ "(negative cache)", gid); ++ return true; ++ } ++ ++ return false; ++} ++ + errno_t + nss_protocol_fill_initgr(struct nss_ctx *nss_ctx, + struct nss_cmd_ctx *cmd_ctx, +@@ -344,6 +372,7 @@ nss_protocol_fill_initgr(struct nss_ctx *nss_ctx, + size_t body_len; + size_t rp; + gid_t gid; ++ const char *grp_name; + gid_t orig_gid; + errno_t ret; + int i; +@@ -392,6 +421,8 @@ nss_protocol_fill_initgr(struct nss_ctx *nss_ctx, + gid = sss_view_ldb_msg_find_attr_as_uint64(domain, msg, SYSDB_GIDNUM, + 0); + posix = ldb_msg_find_attr_as_string(msg, SYSDB_POSIX, NULL); ++ grp_name = sss_view_ldb_msg_find_attr_as_string(domain, msg, SYSDB_NAME, ++ NULL); + + if (gid == 0) { + if (posix != NULL && strcmp(posix, "FALSE") == 0) { +@@ -404,6 +435,10 @@ nss_protocol_fill_initgr(struct nss_ctx *nss_ctx, + } + } + ++ if (is_group_filtered(nss_ctx->rctx->ncache, domain, grp_name, gid)) { ++ continue; ++ } ++ + SAFEALIGN_COPY_UINT32(&body[rp], &gid, &rp); + num_results++; + +diff --git a/src/tests/intg/test_ldap.py b/src/tests/intg/test_ldap.py +index 194d7d9cc..6a78c960f 100644 +--- a/src/tests/intg/test_ldap.py ++++ b/src/tests/intg/test_ldap.py +@@ -1190,6 +1190,18 @@ def test_nss_filters(ldap_conn, sanity_nss_filter): + with pytest.raises(KeyError): + grp.getgrgid(14) + ++ # test initgroups - user1 is member of group_two_one_user_groups (2019) ++ # which is filtered out ++ (res, errno, gids) = sssd_id.call_sssd_initgroups("user1", 2001) ++ assert res == sssd_id.NssReturnCode.SUCCESS ++ ++ user_with_group_ids = [2001, 2012, 2015, 2017, 2018] ++ assert sorted(gids) == sorted(user_with_group_ids), \ ++ "result: %s\n expected %s" % ( ++ ", ".join(["%s" % s for s in sorted(gids)]), ++ ", ".join(["%s" % s for s in sorted(user_with_group_ids)]) ++ ) ++ + + @pytest.fixture + def sanity_nss_filter_cached(request, ldap_conn): +-- +2.21.3 + diff --git a/SOURCES/0011-ifp-fix-use-after-free.patch b/SOURCES/0011-ifp-fix-use-after-free.patch new file mode 100644 index 0000000..8e42b4d --- /dev/null +++ b/SOURCES/0011-ifp-fix-use-after-free.patch @@ -0,0 +1,36 @@ +From 81e757b7b1d69893b5725f9c148c55d89c779e7b Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Tue, 3 Nov 2020 10:12:15 +0100 +Subject: [PATCH] ifp: fix use-after-free +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The variable fqdn is pointing to some data from state->res->msgs[0]. But +before fqdn is used in the next search state->res and the memory +hierarchy below is freed. As a result the location where fqdn is pointing +to might hold the expected data or other data and the search will fail +intermittently. + +Resolves: https://github.com/SSSD/sssd/issues/5382 + +Reviewed-by: Pavel Březina +--- + src/responder/ifp/ifpsrv_cmd.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/responder/ifp/ifpsrv_cmd.c b/src/responder/ifp/ifpsrv_cmd.c +index 9f20bf2db..d95618127 100644 +--- a/src/responder/ifp/ifpsrv_cmd.c ++++ b/src/responder/ifp/ifpsrv_cmd.c +@@ -128,6 +128,7 @@ static void ifp_user_get_attr_done(struct tevent_req *subreq) + tevent_req_error(req, ERR_INTERNAL); + return; + } ++ fqdn = talloc_steal(state, fqdn); + + if (state->search_type == SSS_DP_USER) { + /* throw away the result and perform attr search */ +-- +2.21.3 + diff --git a/SOURCES/0012-ifp-fix-original-fix-use-after-free.patch b/SOURCES/0012-ifp-fix-original-fix-use-after-free.patch new file mode 100644 index 0000000..8e87526 --- /dev/null +++ b/SOURCES/0012-ifp-fix-original-fix-use-after-free.patch @@ -0,0 +1,38 @@ +From 3b158934cbb8f87cbfaf1650389b8dcd654b92ca Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Thu, 19 Nov 2020 18:05:00 +0100 +Subject: [PATCH] ifp: fix original fix use-after-free + +The original fix stole the fqdn too earlier. Only for SSS_DP_USER +requests the steal is important. For other request where the first +result is returned to the caller the original version +might even cause issues since the name does not belong to the memory +hierarchy of the result anymore. + +Resolves: https://github.com/SSSD/sssd/issues/5382 + +Reviewed-by: Alexey Tikhonov +--- + src/responder/ifp/ifpsrv_cmd.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/responder/ifp/ifpsrv_cmd.c b/src/responder/ifp/ifpsrv_cmd.c +index d95618127..8cf1ec84c 100644 +--- a/src/responder/ifp/ifpsrv_cmd.c ++++ b/src/responder/ifp/ifpsrv_cmd.c +@@ -128,10 +128,10 @@ static void ifp_user_get_attr_done(struct tevent_req *subreq) + tevent_req_error(req, ERR_INTERNAL); + return; + } +- fqdn = talloc_steal(state, fqdn); + + if (state->search_type == SSS_DP_USER) { +- /* throw away the result and perform attr search */ ++ /* throw away the result but keep the fqdn and perform attr search */ ++ fqdn = talloc_steal(state, fqdn); + talloc_zfree(state->res); + + ret = sysdb_get_user_attr_with_views(state, state->dom, fqdn, +-- +2.21.3 + diff --git a/SOURCES/0013-pam_sss-use-unique-id-for-gdm-choice-list.patch b/SOURCES/0013-pam_sss-use-unique-id-for-gdm-choice-list.patch new file mode 100644 index 0000000..c374782 --- /dev/null +++ b/SOURCES/0013-pam_sss-use-unique-id-for-gdm-choice-list.patch @@ -0,0 +1,68 @@ +From 1b9b7f5a635ede8eee90d13bfe0e1f87e51191a9 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Fri, 13 Nov 2020 12:59:39 +0100 +Subject: [PATCH 13/16] pam_sss: use unique id for gdm choice list + +Currently the key-id read from the Smartcard is used as key value for +the gdm choice list dialog. Since it might be possible that multiple +certificates use the same key and hence the same key-id this is not a +suitable value. + +With this patch the string representation of a numerical counter is used. + +Resolves: https://github.com/SSSD/sssd/issues/5400 + +Reviewed-by: Alexey Tikhonov +--- + src/sss_client/pam_sss.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/src/sss_client/pam_sss.c b/src/sss_client/pam_sss.c +index b844d257e..04dfdb55d 100644 +--- a/src/sss_client/pam_sss.c ++++ b/src/sss_client/pam_sss.c +@@ -128,6 +128,7 @@ struct cert_auth_info { + char *key_id; + char *prompt_str; + char *pam_cert_user; ++ char *choice_list_id; + struct cert_auth_info *prev; + struct cert_auth_info *next; + }; +@@ -141,6 +142,7 @@ static void free_cai(struct cert_auth_info *cai) + free(cai->module_name); + free(cai->key_id); + free(cai->prompt_str); ++ free(cai->choice_list_id); + free(cai); + } + } +@@ -1698,7 +1700,15 @@ static int prompt_multi_cert_gdm(pam_handle_t *pamh, struct pam_items *pi) + ret = ENOMEM; + goto done; + } +- request->list.items[c].key = cai->key_id; ++ free(cai->choice_list_id); ++ ret = asprintf(&cai->choice_list_id, "%zu", c); ++ if (ret == -1) { ++ cai->choice_list_id = NULL; ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ request->list.items[c].key = cai->choice_list_id; + request->list.items[c++].text = prompt; + } + +@@ -1719,7 +1729,7 @@ static int prompt_multi_cert_gdm(pam_handle_t *pamh, struct pam_items *pi) + } + + DLIST_FOR_EACH(cai, pi->cert_list) { +- if (strcmp(response->key, cai->key_id) == 0) { ++ if (strcmp(response->key, cai->choice_list_id) == 0) { + pam_info(pamh, "Certificate ‘%s’ selected", cai->key_id); + pi->selected_cert = cai; + ret = 0; +-- +2.21.3 + diff --git a/SOURCES/0014-authtok-add-label-to-Smartcard-token.patch b/SOURCES/0014-authtok-add-label-to-Smartcard-token.patch new file mode 100644 index 0000000..741fc5d --- /dev/null +++ b/SOURCES/0014-authtok-add-label-to-Smartcard-token.patch @@ -0,0 +1,1072 @@ +From 8b6be52e95e953ae0431676de0b8c8be7a3262bc Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Fri, 13 Nov 2020 18:05:14 +0100 +Subject: [PATCH 14/16] authtok: add label to Smartcard token + +The key-id might not be sufficient to identify a certificate on a +Smartcard since it is possible that multiple certificates will use the +same key. + +This patch adds the certificate label to the Smartcard authtok item to +resolve the ambiguity if the key-id is used for multiple certificates. + +Resolves: https://github.com/SSSD/sssd/issues/5400 + +Reviewed-by: Alexey Tikhonov +--- + src/p11_child/p11_child.h | 3 +- + src/p11_child/p11_child_common.c | 12 +++-- + src/p11_child/p11_child_openssl.c | 16 +++++-- + src/providers/krb5/krb5_child.c | 14 +++++- + src/responder/pam/pamsrv_cmd.c | 5 +- + src/responder/pam/pamsrv_p11.c | 8 +++- + src/sss_client/pam_sss.c | 3 ++ + src/tests/cmocka/test_authtok.c | 36 +++++++++------ + src/tests/cmocka/test_pam_srv.c | 65 ++++++++++++++------------ + src/util/authtok-utils.c | 30 ++++++++++-- + src/util/authtok-utils.h | 11 ++++- + src/util/authtok.c | 77 +++++++++++++++++++++++++------ + src/util/authtok.h | 14 +++++- + 13 files changed, 214 insertions(+), 80 deletions(-) + +diff --git a/src/p11_child/p11_child.h b/src/p11_child/p11_child.h +index 0b53e70c5..9c0cefe05 100644 +--- a/src/p11_child/p11_child.h ++++ b/src/p11_child/p11_child.h +@@ -68,7 +68,8 @@ bool do_verification_b64(struct p11_ctx *p11_ctx, const char *cert_b64); + errno_t do_card(TALLOC_CTX *mem_ctx, struct p11_ctx *p11_ctx, + enum op_mode mode, const char *pin, + const char *module_name_in, const char *token_name_in, +- const char *key_id_in, const char *uri, char **_multi); ++ const char *key_id_in, const char *label, ++ const char *uri, char **_multi); + + errno_t parse_cert_verify_opts(TALLOC_CTX *mem_ctx, const char *verify_opts, + struct cert_verify_opts **cert_verify_opts); +diff --git a/src/p11_child/p11_child_common.c b/src/p11_child/p11_child_common.c +index 236d7dac4..f17de1a9e 100644 +--- a/src/p11_child/p11_child_common.c ++++ b/src/p11_child/p11_child_common.c +@@ -60,7 +60,8 @@ static int do_work(TALLOC_CTX *mem_ctx, enum op_mode mode, const char *ca_db, + bool wait_for_card, + const char *cert_b64, const char *pin, + const char *module_name, const char *token_name, +- const char *key_id, const char *uri, char **multi) ++ const char *key_id, const char *label, const char *uri, ++ char **multi) + { + int ret; + struct p11_ctx *p11_ctx; +@@ -91,7 +92,7 @@ static int do_work(TALLOC_CTX *mem_ctx, enum op_mode mode, const char *ca_db, + } + } else { + ret = do_card(mem_ctx, p11_ctx, mode, pin, +- module_name, token_name, key_id, uri, multi); ++ module_name, token_name, key_id, label, uri, multi); + } + + done: +@@ -158,6 +159,7 @@ int main(int argc, const char *argv[]) + char *module_name = NULL; + char *token_name = NULL; + char *key_id = NULL; ++ char *label = NULL; + char *cert_b64 = NULL; + bool wait_for_card = false; + char *uri = NULL; +@@ -194,6 +196,8 @@ int main(int argc, const char *argv[]) + _("Token name for authentication"), NULL}, + {"key_id", 0, POPT_ARG_STRING, &key_id, 0, + _("Key ID for authentication"), NULL}, ++ {"label", 0, POPT_ARG_STRING, &label, 0, ++ _("Label for authentication"), NULL}, + {"certificate", 0, POPT_ARG_STRING, &cert_b64, 0, + _("certificate to verify, base64 encoded"), NULL}, + {"uri", 0, POPT_ARG_STRING, &uri, 0, +@@ -340,6 +344,7 @@ int main(int argc, const char *argv[]) + } + talloc_steal(main_ctx, debug_prg_name); + ++ /* We do not require the label, but it is recommended */ + if (mode == OP_AUTH && (module_name == NULL || token_name == NULL + || key_id == NULL)) { + DEBUG(SSSDBG_FATAL_FAILURE, +@@ -369,7 +374,8 @@ int main(int argc, const char *argv[]) + } + + ret = do_work(main_ctx, mode, ca_db, cert_verify_opts, wait_for_card, +- cert_b64, pin, module_name, token_name, key_id, uri, &multi); ++ cert_b64, pin, module_name, token_name, key_id, label, uri, ++ &multi); + if (ret != 0) { + DEBUG(SSSDBG_OP_FAILURE, "do_work failed.\n"); + goto fail; +diff --git a/src/p11_child/p11_child_openssl.c b/src/p11_child/p11_child_openssl.c +index 04b3e1467..d81a1a9ea 100644 +--- a/src/p11_child/p11_child_openssl.c ++++ b/src/p11_child/p11_child_openssl.c +@@ -1587,7 +1587,8 @@ static errno_t wait_for_card(CK_FUNCTION_LIST *module, CK_SLOT_ID *slot_id) + errno_t do_card(TALLOC_CTX *mem_ctx, struct p11_ctx *p11_ctx, + enum op_mode mode, const char *pin, + const char *module_name_in, const char *token_name_in, +- const char *key_id_in, const char *uri_str, char **_multi) ++ const char *key_id_in, const char *label_in, ++ const char *uri_str, char **_multi) + { + int ret; + size_t c; +@@ -1845,11 +1846,13 @@ errno_t do_card(TALLOC_CTX *mem_ctx, struct p11_ctx *p11_ctx, + DLIST_FOR_EACH(item, all_cert_list) { + /* Check if we found the certificates we needed for authentication or + * the requested ones for pre-auth. For authentication all attributes +- * must be given and match, for pre-auth only the given ones must +- * match. */ +- DEBUG(SSSDBG_TRACE_ALL, "%s %s %s %s %s %s.\n", ++ * except the label must be given and match. The label is optional for ++ * authentication but if given it must match as well. For pre-auth ++ * only the given ones must match. */ ++ DEBUG(SSSDBG_TRACE_ALL, "%s %s %s %s %s %s %s.\n", + module_name_in, module_file_name, token_name_in, token_name, +- key_id_in, item->id); ++ key_id_in, label_in == NULL ? "- no label given-" : label_in, ++ item->id); + + if ((mode == OP_AUTH + && module_name_in != NULL +@@ -1857,6 +1860,9 @@ errno_t do_card(TALLOC_CTX *mem_ctx, struct p11_ctx *p11_ctx, + && key_id_in != NULL + && item->id != NULL + && strcmp(key_id_in, item->id) == 0 ++ && (label_in == NULL ++ || (label_in != NULL && item->label != NULL ++ && strcmp(label_in, item->label) == 0)) + && strcmp(token_name_in, token_name) == 0 + && strcmp(module_name_in, module_file_name) == 0) + || (mode == OP_PREAUTH +diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c +index 6e2bf6d75..cab7b27a2 100644 +--- a/src/providers/krb5/krb5_child.c ++++ b/src/providers/krb5/krb5_child.c +@@ -714,7 +714,7 @@ static krb5_error_code answer_pkinit(krb5_context ctx, + kerr = sss_authtok_get_sc(kr->pd->authtok, &pin, NULL, + &token_name, NULL, + &module_name, NULL, +- NULL, NULL); ++ NULL, NULL, NULL, NULL); + if (kerr != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "sss_authtok_get_sc failed.\n"); +@@ -1226,11 +1226,12 @@ static errno_t get_pkinit_identity(TALLOC_CTX *mem_ctx, + const char *token_name; + const char *module_name; + const char *key_id; ++ const char *label; + + ret = sss_authtok_get_sc(authtok, NULL, NULL, + &token_name, NULL, + &module_name, NULL, +- &key_id, NULL); ++ &key_id, NULL, &label, NULL); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sss_authtok_get_sc failed.\n"); + return ret; +@@ -1267,6 +1268,15 @@ static errno_t get_pkinit_identity(TALLOC_CTX *mem_ctx, + } + } + ++ if (label != NULL && *label != '\0') { ++ identity = talloc_asprintf_append(identity, ":certlabel=%s", label); ++ if (identity == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "talloc_asprintf_append failed.\n"); ++ return ENOMEM; ++ } ++ } ++ + *_identity = identity; + + DEBUG(SSSDBG_TRACE_ALL, "Using pkinit identity [%s].\n", identity); +diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c +index 9ea488be4..d3f092b2b 100644 +--- a/src/responder/pam/pamsrv_cmd.c ++++ b/src/responder/pam/pamsrv_cmd.c +@@ -1258,7 +1258,7 @@ static errno_t pam_forwarder_parse_data(struct cli_ctx *cctx, struct pam_data *p + || sss_authtok_get_type(pd->authtok) + == SSS_AUTHTOK_TYPE_SC_KEYPAD)) { + ret = sss_authtok_get_sc(pd->authtok, NULL, NULL, NULL, NULL, NULL, +- NULL, &key_id, NULL); ++ NULL, &key_id, NULL, NULL, NULL); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sss_authtok_get_sc failed.\n"); + goto done; +@@ -2274,7 +2274,8 @@ static void pam_dom_forwarder(struct pam_auth_req *preq) + SSS_AUTHTOK_TYPE_SC_PIN, NULL, 0, + sss_cai_get_token_name(preq->current_cert), 0, + sss_cai_get_module_name(preq->current_cert), 0, +- sss_cai_get_key_id(preq->current_cert), 0); ++ sss_cai_get_key_id(preq->current_cert), 0, ++ sss_cai_get_label(preq->current_cert), 0); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "sss_authtok_set_sc failed, Smartcard " +diff --git a/src/responder/pam/pamsrv_p11.c b/src/responder/pam/pamsrv_p11.c +index abc987804..23f94927a 100644 +--- a/src/responder/pam/pamsrv_p11.c ++++ b/src/responder/pam/pamsrv_p11.c +@@ -727,6 +727,7 @@ struct tevent_req *pam_check_cert_send(TALLOC_CTX *mem_ctx, + const char *module_name = NULL; + const char *token_name = NULL; + const char *key_id = NULL; ++ const char *label = NULL; + + req = tevent_req_create(mem_ctx, &state, struct pam_check_cert_state); + if (req == NULL) { +@@ -766,7 +767,8 @@ struct tevent_req *pam_check_cert_send(TALLOC_CTX *mem_ctx, + if (sss_authtok_get_type(pd->authtok) == SSS_AUTHTOK_TYPE_SC_PIN + || sss_authtok_get_type(pd->authtok) == SSS_AUTHTOK_TYPE_SC_KEYPAD) { + ret = sss_authtok_get_sc(pd->authtok, NULL, NULL, &token_name, NULL, +- &module_name, NULL, &key_id, NULL); ++ &module_name, NULL, &key_id, NULL, ++ &label, NULL); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sss_authtok_get_sc failed.\n"); + goto done; +@@ -784,6 +786,10 @@ struct tevent_req *pam_check_cert_send(TALLOC_CTX *mem_ctx, + extra_args[arg_c++] = key_id; + extra_args[arg_c++] = "--key_id"; + } ++ if (label != NULL && *label != '\0') { ++ extra_args[arg_c++] = label; ++ extra_args[arg_c++] = "--label"; ++ } + } + + if (pd->cmd == SSS_PAM_AUTHENTICATE) { +diff --git a/src/sss_client/pam_sss.c b/src/sss_client/pam_sss.c +index 04dfdb55d..cffbfa770 100644 +--- a/src/sss_client/pam_sss.c ++++ b/src/sss_client/pam_sss.c +@@ -126,6 +126,7 @@ struct cert_auth_info { + char *token_name; + char *module_name; + char *key_id; ++ char *label; + char *prompt_str; + char *pam_cert_user; + char *choice_list_id; +@@ -1962,6 +1963,7 @@ static int prompt_sc_pin(pam_handle_t *pamh, struct pam_items *pi) + ret = sss_auth_pack_sc_blob(answer, 0, cai->token_name, 0, + cai->module_name, 0, + cai->key_id, 0, ++ cai->label, 0, + NULL, 0, &needed_size); + if (ret != EAGAIN) { + D(("sss_auth_pack_sc_blob failed.")); +@@ -1979,6 +1981,7 @@ static int prompt_sc_pin(pam_handle_t *pamh, struct pam_items *pi) + ret = sss_auth_pack_sc_blob(answer, 0, cai->token_name, 0, + cai->module_name, 0, + cai->key_id, 0, ++ cai->label, 0, + (uint8_t *) pi->pam_authtok, needed_size, + &needed_size); + if (ret != EOK) { +diff --git a/src/tests/cmocka/test_authtok.c b/src/tests/cmocka/test_authtok.c +index a8f5bdee7..a31014eb6 100644 +--- a/src/tests/cmocka/test_authtok.c ++++ b/src/tests/cmocka/test_authtok.c +@@ -451,25 +451,27 @@ void test_sss_authtok_sc_blobs(void **state) + size_t module_name_len; + const char *key_id; + size_t key_id_len; ++ const char *label; ++ size_t label_len; + + ts = talloc_get_type_abort(*state, struct test_state); + + ret = sss_auth_pack_sc_blob("abc", 0, "defg", 0, "hijkl", 0, "mnopqr", 0, +- NULL, 0, &needed_size); ++ "stuvw", 0, NULL, 0, &needed_size); + assert_int_equal(ret, EAGAIN); + + buf = talloc_size(ts, needed_size); + assert_non_null(buf); + + ret = sss_auth_pack_sc_blob("abc", 0, "defg", 0, "hijkl", 0, "mnopqr", 0, +- buf, needed_size, &needed_size); ++ "stuvw", 0, buf, needed_size, &needed_size); + assert_int_equal(ret, EOK); + + #if __BYTE_ORDER == __LITTLE_ENDIAN +- assert_memory_equal(buf, "\4\0\0\0\5\0\0\0\6\0\0\0\7\0\0\0abc\0defg\0hijkl\0mnopqr\0", ++ assert_memory_equal(buf, "\4\0\0\0\5\0\0\0\6\0\0\0\7\0\0\0\6\0\0\0abc\0defg\0hijkl\0mnopqr\0stuvw\0", + needed_size); + #else +- assert_memory_equal(buf, "\0\0\0\4\0\0\0\5\0\0\0\6\0\0\0\7abc\0defg\0hijkl\0mnopqr\0", ++ assert_memory_equal(buf, "\0\0\0\4\0\0\0\5\0\0\0\6\0\0\0\7\0\0\0\6abc\0defg\0hijkl\0mnopqr\0stuvw\0", + needed_size); + #endif + +@@ -485,7 +487,8 @@ void test_sss_authtok_sc_blobs(void **state) + ret = sss_authtok_get_sc(ts->authtoken, &pin, &pin_len, + &token_name, &token_name_len, + &module_name, &module_name_len, +- &key_id, &key_id_len); ++ &key_id, &key_id_len, ++ &label, &label_len); + assert_int_equal(ret, EOK); + assert_int_equal(pin_len, 3); + assert_string_equal(pin, "abc"); +@@ -495,11 +498,14 @@ void test_sss_authtok_sc_blobs(void **state) + assert_string_equal(module_name, "hijkl"); + assert_int_equal(key_id_len, 6); + assert_string_equal(key_id, "mnopqr"); ++ assert_int_equal(label_len, 5); ++ assert_string_equal(label, "stuvw"); + + ret = sss_authtok_get_sc(ts->authtoken, NULL, NULL, + &token_name, &token_name_len, + &module_name, &module_name_len, +- &key_id, &key_id_len); ++ &key_id, &key_id_len, ++ &label, &label_len); + assert_int_equal(ret, EOK); + assert_int_equal(token_name_len, 4); + assert_string_equal(token_name, "defg"); +@@ -507,15 +513,19 @@ void test_sss_authtok_sc_blobs(void **state) + assert_string_equal(module_name, "hijkl"); + assert_int_equal(key_id_len, 6); + assert_string_equal(key_id, "mnopqr"); ++ assert_int_equal(label_len, 5); ++ assert_string_equal(label, "stuvw"); + + ret = sss_authtok_get_sc(ts->authtoken, NULL, NULL, + &token_name, NULL, + &module_name, NULL, +- &key_id, NULL); ++ &key_id, NULL, ++ &label, NULL); + assert_int_equal(ret, EOK); + assert_string_equal(token_name, "defg"); + assert_string_equal(module_name, "hijkl"); + assert_string_equal(key_id, "mnopqr"); ++ assert_string_equal(label, "stuvw"); + + sss_authtok_set_empty(ts->authtoken); + talloc_free(buf); +@@ -608,14 +618,14 @@ void test_sss_authtok_sc_pin(void **state) + assert_int_equal(sss_authtok_get_type(ts->authtoken), + SSS_AUTHTOK_TYPE_SC_PIN); + size = sss_authtok_get_size(ts->authtoken); +- assert_int_equal(size, 28); ++ assert_int_equal(size, 33); + #if __BYTE_ORDER == __LITTLE_ENDIAN + assert_memory_equal(sss_authtok_get_data(ts->authtoken), +- "\11\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0" "12345678\0\0\0\0", ++ "\11\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0" "12345678\0\0\0\0\0", + size); + #else + assert_memory_equal(sss_authtok_get_data(ts->authtoken), +- "\0\0\0\11\0\0\0\1\0\0\0\1\0\0\0\1" "12345678\0\0\0\0", ++ "\0\0\0\11\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1" "12345678\0\0\0\0\0", + size); + #endif + +@@ -624,14 +634,14 @@ void test_sss_authtok_sc_pin(void **state) + assert_int_equal(sss_authtok_get_type(ts->authtoken), + SSS_AUTHTOK_TYPE_SC_PIN); + size = sss_authtok_get_size(ts->authtoken); +- assert_int_equal(size, 25); ++ assert_int_equal(size, 30); + #if __BYTE_ORDER == __LITTLE_ENDIAN + assert_memory_equal(sss_authtok_get_data(ts->authtoken), +- "\6\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0" "12345\0\0\0\0", ++ "\6\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0" "12345\0\0\0\0\0", + size); + #else + assert_memory_equal(sss_authtok_get_data(ts->authtoken), +- "\0\0\0\6\0\0\0\1\0\0\0\1\0\0\0\1" "12345\0\0\0\0", ++ "\0\0\0\6\0\0\0\1\0\0\0\1\0\0\0\1\0\0\0\1" "12345\0\0\0\0\0", + size); + #endif + +diff --git a/src/tests/cmocka/test_pam_srv.c b/src/tests/cmocka/test_pam_srv.c +index 326deaf1f..cb05042de 100644 +--- a/src/tests/cmocka/test_pam_srv.c ++++ b/src/tests/cmocka/test_pam_srv.c +@@ -536,7 +536,7 @@ static void mock_input_pam(TALLOC_CTX *mem_ctx, + static void mock_input_pam_cert(TALLOC_CTX *mem_ctx, const char *name, + const char *pin, const char *token_name, + const char *module_name, const char *key_id, +- const char *service, ++ const char *label, const char *service, + acct_cb_t acct_cb, const char *cert) + { + size_t buf_size; +@@ -556,14 +556,14 @@ static void mock_input_pam_cert(TALLOC_CTX *mem_ctx, const char *name, + + if (pin != NULL) { + ret = sss_auth_pack_sc_blob(pin, 0, token_name, 0, module_name, 0, +- key_id, 0, NULL, 0, &needed_size); ++ key_id, 0, label, 0, NULL, 0, &needed_size); + assert_int_equal(ret, EAGAIN); + + pi.pam_authtok = malloc(needed_size); + assert_non_null(pi.pam_authtok); + + ret = sss_auth_pack_sc_blob(pin, 0, token_name, 0, module_name, 0, +- key_id, 0, ++ key_id, 0, label, 0, + (uint8_t *)pi.pam_authtok, needed_size, + &needed_size); + assert_int_equal(ret, EOK); +@@ -1766,7 +1766,7 @@ void test_pam_preauth_no_logon_name(void **state) + int ret; + + mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +- NULL); ++ NULL, NULL); + + will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); + will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); +@@ -1862,7 +1862,7 @@ void test_pam_preauth_cert_nocert(void **state) + unsetenv("SOFTHSM2_CONF"); + + mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL, +- NULL, NULL); ++ NULL, NULL, NULL); + + will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); + will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); +@@ -2004,7 +2004,7 @@ void test_pam_preauth_cert_nomatch(void **state) + set_cert_auth_param(pam_test_ctx->pctx, CA_DB); + + mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL, +- test_lookup_by_cert_cb, NULL); ++ NULL, test_lookup_by_cert_cb, NULL); + + will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); + will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); +@@ -2026,7 +2026,7 @@ void test_pam_preauth_cert_match(void **state) + set_cert_auth_param(pam_test_ctx->pctx, CA_DB); + + mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL, +- test_lookup_by_cert_cb, SSSD_TEST_CERT_0001); ++ NULL, test_lookup_by_cert_cb, SSSD_TEST_CERT_0001); + + will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); + will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); +@@ -2048,7 +2048,7 @@ void test_pam_preauth_cert_match_gdm_smartcard(void **state) + + set_cert_auth_param(pam_test_ctx->pctx, CA_DB); + +- mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, ++ mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL, + "gdm-smartcard", test_lookup_by_cert_cb, + SSSD_TEST_CERT_0001); + +@@ -2072,7 +2072,7 @@ void test_pam_preauth_cert_match_wrong_user(void **state) + set_cert_auth_param(pam_test_ctx->pctx, CA_DB); + + mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL, +- test_lookup_by_cert_wrong_user_cb, ++ NULL, test_lookup_by_cert_wrong_user_cb, + SSSD_TEST_CERT_0001); + + will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); +@@ -2104,7 +2104,7 @@ void test_pam_preauth_cert_no_logon_name(void **state) + * request will be done with the username found by the certificate + * lookup. */ + mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL, NULL, NULL, NULL, +- test_lookup_by_cert_cb, SSSD_TEST_CERT_0001); ++ NULL, test_lookup_by_cert_cb, SSSD_TEST_CERT_0001); + mock_account_recv_simple(); + mock_parse_inp("pamuser", NULL, EOK); + mock_parse_inp("pamuser", NULL, EOK); +@@ -2134,7 +2134,7 @@ void test_pam_preauth_cert_no_logon_name_with_hint(void **state) + * during pre-auth and there is no need for an extra mocked response as in + * test_pam_preauth_cert_no_logon_name. */ + mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL, NULL, NULL, NULL, +- test_lookup_by_cert_cb, SSSD_TEST_CERT_0001); ++ NULL, test_lookup_by_cert_cb, SSSD_TEST_CERT_0001); + + will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); + will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); +@@ -2155,7 +2155,7 @@ void test_pam_preauth_cert_no_logon_name_double_cert(void **state) + + set_cert_auth_param(pam_test_ctx->pctx, CA_DB); + +- mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL, NULL, NULL, NULL, ++ mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + test_lookup_by_cert_double_cb, SSSD_TEST_CERT_0001); + + will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); +@@ -2178,7 +2178,7 @@ void test_pam_preauth_cert_no_logon_name_double_cert_with_hint(void **state) + set_cert_auth_param(pam_test_ctx->pctx, CA_DB); + pam_test_ctx->rctx->domains->user_name_hint = true; + +- mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL, NULL, NULL, NULL, ++ mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + test_lookup_by_cert_double_cb, SSSD_TEST_CERT_0001); + + will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); +@@ -2201,7 +2201,7 @@ void test_pam_preauth_no_cert_no_logon_name(void **state) + set_cert_auth_param(pam_test_ctx->pctx, "/no/path"); + + mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL, NULL, NULL, NULL, NULL, +- NULL); ++ NULL, NULL); + + will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); + will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); +@@ -2223,7 +2223,7 @@ void test_pam_preauth_cert_no_logon_name_no_match(void **state) + set_cert_auth_param(pam_test_ctx->pctx, CA_DB); + + mock_input_pam_cert(pam_test_ctx, NULL, NULL, NULL, NULL, NULL, NULL, +- test_lookup_by_cert_cb, NULL); ++ NULL, test_lookup_by_cert_cb, NULL); + + will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); + will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); +@@ -2252,7 +2252,8 @@ void test_pam_cert_auth(void **state) + * in the cache and no second request to the backend is needed. */ + mock_input_pam_cert(pam_test_ctx, "pamuser", "123456", "SSSD Test Token", + TEST_MODULE_NAME, +- "C554C9F82C2A9D58B70921C143304153A8A42F17", NULL, ++ "C554C9F82C2A9D58B70921C143304153A8A42F17", ++ "SSSD test cert 0001", NULL, + test_lookup_by_cert_cb, SSSD_TEST_CERT_0001); + + will_return(__wrap_sss_packet_get_cmd, SSS_PAM_AUTHENTICATE); +@@ -2289,7 +2290,8 @@ void test_pam_ecc_cert_auth(void **state) + mock_input_pam_cert(pam_test_ctx, "pamuser", "123456", + "SSSD Test ECC Token", + TEST_MODULE_NAME, +- "190E513C9A3DFAACDE5D2D0592F0FDFF559C10CB", NULL, ++ "190E513C9A3DFAACDE5D2D0592F0FDFF559C10CB", ++ "SSSD test ECC cert 0001", NULL, + test_lookup_by_cert_cb, SSSD_TEST_ECC_CERT_0001); + + will_return(__wrap_sss_packet_get_cmd, SSS_PAM_AUTHENTICATE); +@@ -2324,7 +2326,8 @@ void test_pam_cert_auth_no_logon_name(void **state) + * in the cache and no second request to the backend is needed. */ + mock_input_pam_cert(pam_test_ctx, NULL, "123456", "SSSD Test Token", + TEST_MODULE_NAME, +- "C554C9F82C2A9D58B70921C143304153A8A42F17", NULL, ++ "C554C9F82C2A9D58B70921C143304153A8A42F17", ++ "SSSD test cert 0001", NULL, + test_lookup_by_cert_cb, SSSD_TEST_CERT_0001); + + mock_account_recv_simple(); +@@ -2360,7 +2363,7 @@ void test_pam_cert_auth_no_logon_name_no_key_id(void **state) + * to the user entry the lookup by certificate will already find the user + * in the cache and no second request to the backend is needed. */ + mock_input_pam_cert(pam_test_ctx, NULL, "123456", "SSSD Test Token", +- TEST_MODULE_NAME, NULL, NULL, ++ TEST_MODULE_NAME, NULL, NULL, NULL, + NULL, NULL); + + will_return(__wrap_sss_packet_get_cmd, SSS_PAM_AUTHENTICATE); +@@ -2387,7 +2390,8 @@ void test_pam_cert_auth_double_cert(void **state) + + mock_input_pam_cert(pam_test_ctx, "pamuser", "123456", "SSSD Test Token", + TEST_MODULE_NAME, +- "C554C9F82C2A9D58B70921C143304153A8A42F17", NULL, ++ "C554C9F82C2A9D58B70921C143304153A8A42F17", ++ "SSSD test cert 0001", NULL, + test_lookup_by_cert_double_cb, SSSD_TEST_CERT_0001); + + will_return(__wrap_sss_packet_get_cmd, SSS_PAM_AUTHENTICATE); +@@ -2416,7 +2420,7 @@ void test_pam_cert_preauth_2certs_one_mapping(void **state) + ret = test_lookup_by_cert_cb(discard_const(SSSD_TEST_CERT_0001)); + assert_int_equal(ret, EOK); + mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL, +- test_lookup_by_cert_cb, NULL); ++ NULL, test_lookup_by_cert_cb, NULL); + + will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); + will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); +@@ -2439,7 +2443,7 @@ void test_pam_cert_preauth_2certs_two_mappings(void **state) + putenv(discard_const("SOFTHSM2_CONF=" ABS_BUILD_DIR "/src/tests/test_CA/softhsm2_two.conf")); + + mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL, +- test_lookup_by_cert_cb_2nd_cert_same_user, ++ NULL, test_lookup_by_cert_cb_2nd_cert_same_user, + SSSD_TEST_CERT_0001); + + will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); +@@ -2464,7 +2468,8 @@ void test_pam_cert_auth_2certs_one_mapping(void **state) + + mock_input_pam_cert(pam_test_ctx, "pamuser", "123456", "SSSD Test Token", + TEST_MODULE_NAME, +- "C554C9F82C2A9D58B70921C143304153A8A42F17", NULL, ++ "C554C9F82C2A9D58B70921C143304153A8A42F17", ++ "SSSD test cert 0001", NULL, + test_lookup_by_cert_double_cb, SSSD_TEST_CERT_0001); + + will_return(__wrap_sss_packet_get_cmd, SSS_PAM_AUTHENTICATE); +@@ -2498,7 +2503,7 @@ void test_pam_cert_preauth_uri_token1(void **state) + putenv(discard_const("SOFTHSM2_CONF=" ABS_BUILD_DIR "/src/tests/test_CA/softhsm2_2tokens.conf")); + + mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL, +- test_lookup_by_cert_cb, SSSD_TEST_CERT_0001); ++ NULL, test_lookup_by_cert_cb, SSSD_TEST_CERT_0001); + + will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); + will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); +@@ -2528,7 +2533,7 @@ void test_pam_cert_preauth_uri_token2(void **state) + putenv(discard_const("SOFTHSM2_CONF=" ABS_BUILD_DIR "/src/tests/test_CA/softhsm2_2tokens.conf")); + + mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL, +- test_lookup_by_cert_cb, SSSD_TEST_CERT_0002); ++ NULL, test_lookup_by_cert_cb, SSSD_TEST_CERT_0002); + + will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); + will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); +@@ -2567,7 +2572,7 @@ void test_pam_preauth_expired_crl_file(void **state) + set_cert_auth_param(pam_test_ctx->pctx, CA_DB); + + mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL, +- NULL, NULL); ++ NULL, NULL, NULL); + + will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); + will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); +@@ -2599,7 +2604,7 @@ void test_pam_preauth_expired_crl_file_soft(void **state) + set_cert_auth_param(pam_test_ctx->pctx, CA_DB); + + mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL, +- test_lookup_by_cert_cb, SSSD_TEST_CERT_0001); ++ NULL, test_lookup_by_cert_cb, SSSD_TEST_CERT_0001); + + will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); + will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); +@@ -2632,7 +2637,7 @@ void test_pam_preauth_ocsp(void **state) + putenv(discard_const("SOFTHSM2_CONF=" ABS_BUILD_DIR "/src/tests/test_CA/softhsm2_ocsp.conf")); + + mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL, +- NULL, NULL); ++ NULL, NULL, NULL); + + will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); + will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); +@@ -2674,7 +2679,7 @@ void test_pam_preauth_ocsp_no_ocsp(void **state) + putenv(discard_const("SOFTHSM2_CONF=" ABS_BUILD_DIR "/src/tests/test_CA/softhsm2_ocsp.conf")); + + mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL, +- test_lookup_by_cert_cb, SSSD_TEST_CERT_0005); ++ NULL, test_lookup_by_cert_cb, SSSD_TEST_CERT_0005); + + will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); + will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); +@@ -2708,7 +2713,7 @@ void test_pam_preauth_ocsp_soft_ocsp(void **state) + putenv(discard_const("SOFTHSM2_CONF=" ABS_BUILD_DIR "/src/tests/test_CA/softhsm2_ocsp.conf")); + + mock_input_pam_cert(pam_test_ctx, "pamuser", NULL, NULL, NULL, NULL, NULL, +- test_lookup_by_cert_cb, SSSD_TEST_CERT_0005); ++ NULL, test_lookup_by_cert_cb, SSSD_TEST_CERT_0005); + + will_return(__wrap_sss_packet_get_cmd, SSS_PAM_PREAUTH); + will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); +diff --git a/src/util/authtok-utils.c b/src/util/authtok-utils.c +index e50f86741..e76bd17c5 100644 +--- a/src/util/authtok-utils.c ++++ b/src/util/authtok-utils.c +@@ -77,6 +77,7 @@ errno_t sss_auth_pack_sc_blob(const char *pin, size_t pin_len, + const char *token_name, size_t token_name_len, + const char *module_name, size_t module_name_len, + const char *key_id, size_t key_id_len, ++ const char *label, size_t label_len, + uint8_t *buf, size_t buf_len, + size_t *_sc_blob_len) + { +@@ -88,7 +89,8 @@ errno_t sss_auth_pack_sc_blob(const char *pin, size_t pin_len, + || (pin_len != 0 && pin == NULL) + || (token_name_len != 0 && token_name == NULL) + || (module_name_len != 0 && module_name == NULL) +- || (key_id_len != 0 && key_id == NULL)) { ++ || (key_id_len != 0 && key_id == NULL) ++ || (label_len != 0 && label == NULL)) { + return EINVAL; + } + +@@ -113,6 +115,11 @@ errno_t sss_auth_pack_sc_blob(const char *pin, size_t pin_len, + key_id_len = 0; + } + ++ if (label == NULL) { ++ label = ""; ++ label_len = 0; ++ } ++ + /* len should not include the trailing \0 */ + if (pin_len == 0 || pin[pin_len - 1] == '\0') { + pin_len = strlen(pin); +@@ -130,8 +137,12 @@ errno_t sss_auth_pack_sc_blob(const char *pin, size_t pin_len, + key_id_len = strlen(key_id); + } + +- *_sc_blob_len = pin_len + token_name_len + module_name_len + key_id_len + 4 +- + 4 * sizeof(uint32_t); ++ if (label_len == 0 || label[label_len - 1] == '\0') { ++ label_len = strlen(label); ++ } ++ ++ *_sc_blob_len = pin_len + token_name_len + module_name_len + key_id_len ++ + label_len + 5 + 5 * sizeof(uint32_t); + if (buf == NULL || buf_len < *_sc_blob_len) { + return EAGAIN; + } +@@ -145,6 +156,8 @@ errno_t sss_auth_pack_sc_blob(const char *pin, size_t pin_len, + SAFEALIGN_COPY_UINT32(buf + c, &tmp_uint32_t, &c); + tmp_uint32_t = (uint32_t) key_id_len + 1; + SAFEALIGN_COPY_UINT32(buf + c, &tmp_uint32_t, &c); ++ tmp_uint32_t = (uint32_t) label_len + 1; ++ SAFEALIGN_COPY_UINT32(buf + c, &tmp_uint32_t, &c); + + memcpy(buf + c, pin, pin_len); + buf[c + pin_len] = '\0'; +@@ -160,6 +173,10 @@ errno_t sss_auth_pack_sc_blob(const char *pin, size_t pin_len, + + memcpy(buf + c, key_id, key_id_len); + buf[c + key_id_len] = '\0'; ++ c += key_id_len +1; ++ ++ memcpy(buf + c, label, label_len); ++ buf[c + label_len] = '\0'; + + return 0; + } +@@ -171,6 +188,7 @@ const char *sss_auth_get_pin_from_sc_blob(uint8_t *blob, size_t blob_len) + uint32_t token_name_len; + uint32_t module_name_len; + uint32_t key_id_len; ++ uint32_t label_len; + + if (blob == NULL || blob_len == 0) { + return NULL; +@@ -184,9 +202,11 @@ const char *sss_auth_get_pin_from_sc_blob(uint8_t *blob, size_t blob_len) + SAFEALIGN_COPY_UINT32(&token_name_len, blob + c, &c); + SAFEALIGN_COPY_UINT32(&module_name_len, blob + c, &c); + SAFEALIGN_COPY_UINT32(&key_id_len, blob + c, &c); ++ SAFEALIGN_COPY_UINT32(&label_len, blob + c, &c); + +- if (blob_len != 4 * sizeof(uint32_t) + pin_len + token_name_len +- + module_name_len + key_id_len) { ++ if (blob_len != 5 * sizeof(uint32_t) + pin_len + token_name_len ++ + module_name_len + key_id_len ++ + label_len) { + return NULL; + } + +diff --git a/src/util/authtok-utils.h b/src/util/authtok-utils.h +index 714c8187e..f3b268f78 100644 +--- a/src/util/authtok-utils.h ++++ b/src/util/authtok-utils.h +@@ -39,6 +39,9 @@ + * @param[in] key_id Key ID of the certificate + * @param[in] key_id_len Length of the key id of the certificate, if 0 + * strlen() will be called internally ++ * @param[in] label Label of the certificate ++ * @param[in] label_len Length of the label of the certificate, if 0 ++ * strlen() will be called internally + * @param[in] buf memory buffer of size buf_len, may be NULL + * @param[in] buf_len size of memory buffer buf + * +@@ -53,6 +56,7 @@ errno_t sss_auth_pack_sc_blob(const char *pin, size_t pin_len, + const char *token_name, size_t token_name_len, + const char *module_name, size_t module_name_len, + const char *key_id, size_t key_id_len, ++ const char *label, size_t label_len, + uint8_t *buf, size_t buf_len, + size_t *_sc_blob_len); + /** +@@ -112,6 +116,10 @@ errno_t sss_auth_unpack_2fa_blob(TALLOC_CTX *mem_ctx, + * @param[out] _token_name_len Length of the token name + * @param[out] _module_name Name of PKCS#11 module, null terminated + * @param[out] _module_name_len Length of the module name ++ * @param[out] _key_id Key ID of the certificate, null terminated ++ * @param[out] _key_id_len Length of the key ID ++ * @param[out] _labe l Label of the certificate, null terminated ++ * @param[out] _label_len Length of the label + * + * @return EOK on success + * EINVAL if input data is not consistent +@@ -122,7 +130,8 @@ errno_t sss_auth_unpack_sc_blob(TALLOC_CTX *mem_ctx, + char **pin, size_t *_pin_len, + char **token_name, size_t *_token_name_len, + char **module_name, size_t *_module_name_len, +- char **key_id, size_t *_key_id_len); ++ char **key_id, size_t *_key_id_len, ++ char **label, size_t *_label_len); + + /** + * @brief Return a pointer to the PIN string in the memory buffer +diff --git a/src/util/authtok.c b/src/util/authtok.c +index f8b44d6d6..7254ed1da 100644 +--- a/src/util/authtok.c ++++ b/src/util/authtok.c +@@ -503,7 +503,8 @@ errno_t sss_authtok_set_sc(struct sss_auth_token *tok, + const char *pin, size_t pin_len, + const char *token_name, size_t token_name_len, + const char *module_name, size_t module_name_len, +- const char *key_id, size_t key_id_len) ++ const char *key_id, size_t key_id_len, ++ const char *label, size_t label_len) + { + int ret; + size_t needed_size; +@@ -518,7 +519,7 @@ errno_t sss_authtok_set_sc(struct sss_auth_token *tok, + + ret = sss_auth_pack_sc_blob(pin, pin_len, token_name, token_name_len, + module_name, module_name_len, +- key_id, key_id_len, NULL, 0, ++ key_id, key_id_len, label, label_len, NULL, 0, + &needed_size); + if (ret != EAGAIN) { + DEBUG(SSSDBG_OP_FAILURE, "sss_auth_pack_sc_blob failed.\n"); +@@ -533,7 +534,7 @@ errno_t sss_authtok_set_sc(struct sss_auth_token *tok, + + ret = sss_auth_pack_sc_blob(pin, pin_len, token_name, token_name_len, + module_name, module_name_len, +- key_id, key_id_len, tok->data, ++ key_id, key_id_len, label, label_len, tok->data, + needed_size, &needed_size); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sss_auth_pack_sc_blob failed.\n"); +@@ -560,6 +561,8 @@ errno_t sss_authtok_set_sc_from_blob(struct sss_auth_token *tok, + size_t module_name_len; + char *key_id = NULL; + size_t key_id_len; ++ char *label = NULL; ++ size_t label_len; + TALLOC_CTX *tmp_ctx; + + if (tok == NULL) { +@@ -579,7 +582,7 @@ errno_t sss_authtok_set_sc_from_blob(struct sss_auth_token *tok, + ret = sss_auth_unpack_sc_blob(tmp_ctx, data, len, &pin, &pin_len, + &token_name, &token_name_len, + &module_name, &module_name_len, +- &key_id, &key_id_len); ++ &key_id, &key_id_len, &label, &label_len); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sss_auth_unpack_sc_blob failed.\n"); + goto done; +@@ -588,7 +591,7 @@ errno_t sss_authtok_set_sc_from_blob(struct sss_auth_token *tok, + ret = sss_authtok_set_sc(tok, SSS_AUTHTOK_TYPE_SC_PIN, pin, pin_len, + token_name, token_name_len, + module_name, module_name_len, +- key_id, key_id_len); ++ key_id, key_id_len, label, label_len); + + done: + talloc_free(tmp_ctx); +@@ -607,7 +610,7 @@ errno_t sss_authtok_set_sc_pin(struct sss_auth_token *tok, const char *pin, + } + + return sss_authtok_set_sc(tok, SSS_AUTHTOK_TYPE_SC_PIN, pin, len, +- NULL, 0, NULL, 0, NULL, 0); ++ NULL, 0, NULL, 0, NULL, 0, NULL, 0); + } + + errno_t sss_authtok_get_sc_pin(struct sss_auth_token *tok, const char **_pin, +@@ -625,7 +628,8 @@ errno_t sss_authtok_get_sc_pin(struct sss_auth_token *tok, const char **_pin, + return ENOENT; + case SSS_AUTHTOK_TYPE_SC_PIN: + ret = sss_authtok_get_sc(tok, &pin, &pin_len, +- NULL, NULL, NULL, NULL, NULL, NULL); ++ NULL, NULL, NULL, NULL, NULL, NULL, ++ NULL, NULL); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "sss_authtok_get_sc failed.\n"); + return ret; +@@ -663,13 +667,15 @@ errno_t sss_auth_unpack_sc_blob(TALLOC_CTX *mem_ctx, + char **pin, size_t *_pin_len, + char **token_name, size_t *_token_name_len, + char **module_name, size_t *_module_name_len, +- char **key_id, size_t *_key_id_len) ++ char **key_id, size_t *_key_id_len, ++ char **label, size_t *_label_len) + { + size_t c; + uint32_t pin_len; + uint32_t token_name_len; + uint32_t module_name_len; + uint32_t key_id_len; ++ uint32_t label_len; + + c = 0; + +@@ -678,14 +684,16 @@ errno_t sss_auth_unpack_sc_blob(TALLOC_CTX *mem_ctx, + token_name_len = 0; + module_name_len = 0; + key_id_len = 0; ++ label_len = 0; + } else if (blob_len > 0 + && strnlen((const char *) blob, blob_len) == blob_len - 1) { + pin_len = blob_len; + token_name_len = 0; + module_name_len = 0; + key_id_len = 0; ++ label_len = 0; + } else { +- if (blob_len < 4 * sizeof(uint32_t)) { ++ if (blob_len < 5 * sizeof(uint32_t)) { + DEBUG(SSSDBG_CRIT_FAILURE, "Blob too small.\n"); + return EINVAL; + } +@@ -694,9 +702,11 @@ errno_t sss_auth_unpack_sc_blob(TALLOC_CTX *mem_ctx, + SAFEALIGN_COPY_UINT32(&token_name_len, blob + c, &c); + SAFEALIGN_COPY_UINT32(&module_name_len, blob + c, &c); + SAFEALIGN_COPY_UINT32(&key_id_len, blob + c, &c); ++ SAFEALIGN_COPY_UINT32(&label_len, blob + c, &c); + +- if (blob_len != 4 * sizeof(uint32_t) + pin_len + token_name_len +- + module_name_len + key_id_len) { ++ if (blob_len != 5 * sizeof(uint32_t) + pin_len + token_name_len ++ + module_name_len + key_id_len ++ + label_len) { + DEBUG(SSSDBG_CRIT_FAILURE, "Blob size mismatch.\n"); + return EINVAL; + } +@@ -756,6 +766,25 @@ errno_t sss_auth_unpack_sc_blob(TALLOC_CTX *mem_ctx, + *key_id = NULL; + } + ++ if (label_len != 0) { ++ *label = talloc_strndup(mem_ctx, ++ (const char *) blob + c + pin_len ++ + token_name_len ++ + module_name_len ++ + key_id_len, ++ label_len); ++ if (*label == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n"); ++ talloc_free(*pin); ++ talloc_free(*token_name); ++ talloc_free(*module_name); ++ talloc_free(*key_id); ++ return ENOMEM; ++ } ++ } else { ++ *label = NULL; ++ } ++ + /* Re-calculate length for the case where \0 was missing in the blob */ + if (_pin_len != NULL) { + *_pin_len = (*pin == NULL) ? 0 : strlen(*pin); +@@ -771,6 +800,10 @@ errno_t sss_auth_unpack_sc_blob(TALLOC_CTX *mem_ctx, + *_key_id_len = (*key_id == NULL) ? 0 : strlen(*key_id); + } + ++ if (_label_len != NULL) { ++ *_label_len = (*label == NULL) ? 0 : strlen(*label); ++ } ++ + return EOK; + } + +@@ -778,13 +811,15 @@ errno_t sss_authtok_get_sc(struct sss_auth_token *tok, + const char **_pin, size_t *_pin_len, + const char **_token_name, size_t *_token_name_len, + const char **_module_name, size_t *_module_name_len, +- const char **_key_id, size_t *_key_id_len) ++ const char **_key_id, size_t *_key_id_len, ++ const char **_label, size_t *_label_len) + { + size_t c = 0; + size_t pin_len; + size_t token_name_len; + size_t module_name_len; + size_t key_id_len; ++ size_t label_len; + uint32_t tmp_uint32_t; + + if (!tok) { +@@ -796,7 +831,7 @@ errno_t sss_authtok_get_sc(struct sss_auth_token *tok, + return (tok->type == SSS_AUTHTOK_TYPE_EMPTY) ? ENOENT : EACCES; + } + +- if (tok->length < 4 * sizeof(uint32_t)) { ++ if (tok->length < 5 * sizeof(uint32_t)) { + DEBUG(SSSDBG_CRIT_FAILURE, "Blob too small.\n"); + return EINVAL; + } +@@ -809,9 +844,12 @@ errno_t sss_authtok_get_sc(struct sss_auth_token *tok, + module_name_len = tmp_uint32_t -1; + SAFEALIGN_COPY_UINT32(&tmp_uint32_t, tok->data + c, &c); + key_id_len = tmp_uint32_t -1; ++ SAFEALIGN_COPY_UINT32(&tmp_uint32_t, tok->data + c, &c); ++ label_len = tmp_uint32_t -1; + +- if (tok->length != 4 * sizeof(uint32_t) + 4 + pin_len + token_name_len +- + module_name_len + key_id_len) { ++ if (tok->length != 5 * sizeof(uint32_t) + 5 + pin_len + token_name_len ++ + module_name_len + key_id_len ++ + label_len) { + DEBUG(SSSDBG_CRIT_FAILURE, "Blob size mismatch.\n"); + return EINVAL; + } +@@ -846,5 +884,14 @@ errno_t sss_authtok_get_sc(struct sss_auth_token *tok, + *_key_id_len = key_id_len; + } + ++ if (_label != NULL) { ++ *_label = (const char *) tok->data + c + pin_len + 1 ++ + token_name_len + 1 + module_name_len + 1 ++ + key_id_len + 1; ++ } ++ if (_label_len != NULL) { ++ *_label_len = label_len; ++ } ++ + return EOK; + } +diff --git a/src/util/authtok.h b/src/util/authtok.h +index f70c9da13..6fd3e9ef0 100644 +--- a/src/util/authtok.h ++++ b/src/util/authtok.h +@@ -296,6 +296,10 @@ void sss_authtok_set_sc_keypad(struct sss_auth_token *tok); + * terminated string containing the PKCS#11 key id + * @param key_id_len The length of the key id string, if set to 0 it will be + * calculated ++ * @param label A pointer to a const char *, that will point to a null ++ * terminated string containing the PKCS#11 label ++ * @param label_len The length of the label string, if set to 0 it will be ++ * calculated + * + * @return EOK on success + * EINVAL unexpected or inval input +@@ -306,7 +310,8 @@ errno_t sss_authtok_set_sc(struct sss_auth_token *tok, + const char *pin, size_t pin_len, + const char *token_name, size_t token_name_len, + const char *module_name, size_t module_name_len, +- const char *key_id, size_t key_id_len); ++ const char *key_id, size_t key_id_len, ++ const char *label, size_t label_len); + /** + * @brief Set a Smart Card authentication data, replacing any previous data + * +@@ -342,6 +347,10 @@ errno_t sss_authtok_set_sc_from_blob(struct sss_auth_token *tok, + * a null terminated string holding the PKCS#11 + * key id, may not be modified or freed + * @param[out] _key_id_len Length of the PKCS#11 key id ++ * @param[out] _label A pointer to a const char *, that will point to ++ * a null terminated string holding the PKCS#11 ++ * label, may not be modified or freed ++ * @param[out] _label_len Length of the PKCS#11 label + * + * Any of the output pointers may be NULL if the caller does not need the + * specific item. +@@ -356,7 +365,8 @@ errno_t sss_authtok_get_sc(struct sss_auth_token *tok, + const char **_pin, size_t *_pin_len, + const char **_token_name, size_t *_token_name_len, + const char **_module_name, size_t *_module_name_len, +- const char **_key_id, size_t *_key_id_len); ++ const char **_key_id, size_t *_key_id_len, ++ const char **_label, size_t *_label_len); + + + /** +-- +2.21.3 + diff --git a/SOURCES/0015-pam_sss-add-certificate-label-to-reply-to-pam_sss.patch b/SOURCES/0015-pam_sss-add-certificate-label-to-reply-to-pam_sss.patch new file mode 100644 index 0000000..88fcc9f --- /dev/null +++ b/SOURCES/0015-pam_sss-add-certificate-label-to-reply-to-pam_sss.patch @@ -0,0 +1,208 @@ +From b8800d3e1b43f2eb28b2df7adb2bcb323bf2d1f1 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Sat, 14 Nov 2020 17:52:35 +0100 +Subject: [PATCH 15/16] pam_sss: add certificate label to reply to pam_sss + +Add the certificate label to the data send back and forth to the pam +module to avoid the ambiguity if two certificates use the same key. + +Resolves: https://github.com/SSSD/sssd/issues/5400 + +Reviewed-by: Alexey Tikhonov +--- + src/responder/pam/pamsrv_p11.c | 13 ++++++++++--- + src/sss_client/pam_sss.c | 15 +++++++++++++++ + src/tests/cmocka/test_pam_srv.c | 20 ++++++++++++++++---- + 3 files changed, 41 insertions(+), 7 deletions(-) + +diff --git a/src/responder/pam/pamsrv_p11.c b/src/responder/pam/pamsrv_p11.c +index 23f94927a..e1fd72e64 100644 +--- a/src/responder/pam/pamsrv_p11.c ++++ b/src/responder/pam/pamsrv_p11.c +@@ -1086,11 +1086,13 @@ static errno_t pack_cert_data(TALLOC_CTX *mem_ctx, const char *sysdb_username, + const char *token_name; + const char *module_name; + const char *key_id; ++ const char *label; + char *prompt; + size_t user_len; + size_t token_len; + size_t module_len; + size_t key_id_len; ++ size_t label_len; + size_t prompt_len; + size_t nss_name_len; + const char *username = ""; +@@ -1113,16 +1115,18 @@ static errno_t pack_cert_data(TALLOC_CTX *mem_ctx, const char *sysdb_username, + token_name = sss_cai_get_token_name(cert_info); + module_name = sss_cai_get_module_name(cert_info); + key_id = sss_cai_get_key_id(cert_info); ++ label = sss_cai_get_label(cert_info); + + user_len = strlen(username) + 1; + token_len = strlen(token_name) + 1; + module_len = strlen(module_name) + 1; + key_id_len = strlen(key_id) + 1; ++ label_len = strlen(label) + 1; + prompt_len = strlen(prompt) + 1; + nss_name_len = strlen(nss_username) +1; + +- msg_len = user_len + token_len + module_len + key_id_len + prompt_len +- + nss_name_len; ++ msg_len = user_len + token_len + module_len + key_id_len + label_len ++ + prompt_len + nss_name_len; + + msg = talloc_zero_size(mem_ctx, msg_len); + if (msg == NULL) { +@@ -1136,8 +1140,11 @@ static errno_t pack_cert_data(TALLOC_CTX *mem_ctx, const char *sysdb_username, + memcpy(msg + user_len + token_len, module_name, module_len); + memcpy(msg + user_len + token_len + module_len, key_id, key_id_len); + memcpy(msg + user_len + token_len + module_len + key_id_len, ++ label, label_len); ++ memcpy(msg + user_len + token_len + module_len + key_id_len + label_len, + prompt, prompt_len); +- memcpy(msg + user_len + token_len + module_len + key_id_len + prompt_len, ++ memcpy(msg + user_len + token_len + module_len + key_id_len + label_len ++ + prompt_len, + nss_username, nss_name_len); + talloc_free(prompt); + +diff --git a/src/sss_client/pam_sss.c b/src/sss_client/pam_sss.c +index cffbfa770..c539d6de6 100644 +--- a/src/sss_client/pam_sss.c ++++ b/src/sss_client/pam_sss.c +@@ -142,6 +142,7 @@ static void free_cai(struct cert_auth_info *cai) + free(cai->token_name); + free(cai->module_name); + free(cai->key_id); ++ free(cai->label); + free(cai->prompt_str); + free(cai->choice_list_id); + free(cai); +@@ -936,6 +937,20 @@ static int parse_cert_info(struct pam_items *pi, uint8_t *buf, size_t len, + goto done; + } + ++ cai->label = strdup((char *) &buf[*p + offset]); ++ if (cai->label == NULL) { ++ D(("strdup failed")); ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ offset += strlen(cai->label) + 1; ++ if (offset >= len) { ++ D(("Cert message size mismatch")); ++ ret = EINVAL; ++ goto done; ++ } ++ + cai->prompt_str = strdup((char *) &buf[*p + offset]); + if (cai->prompt_str == NULL) { + D(("strdup failed")); +diff --git a/src/tests/cmocka/test_pam_srv.c b/src/tests/cmocka/test_pam_srv.c +index cb05042de..5506fbf34 100644 +--- a/src/tests/cmocka/test_pam_srv.c ++++ b/src/tests/cmocka/test_pam_srv.c +@@ -62,13 +62,16 @@ + #define TEST_TOKEN_NAME "SSSD Test Token" + #define TEST_TOKEN2_NAME "SSSD Test Token Number 2" + #define TEST_KEY_ID "C554C9F82C2A9D58B70921C143304153A8A42F17" ++#define TEST_LABEL "SSSD test cert 0001" + #define TEST_MODULE_NAME SOFTHSM2_PATH + #define TEST_PROMPT "SSSD test cert 0001\nCN=SSSD test cert 0001,OU=SSSD test,O=SSSD" + #define TEST2_PROMPT "SSSD test cert 0002\nCN=SSSD test cert 0002,OU=SSSD test,O=SSSD" + #define TEST5_PROMPT "SSSD test cert 0005\nCN=SSSD test cert 0005,OU=SSSD test,O=SSSD" + + #define TEST2_KEY_ID "5405842D56CF31F0BB025A695C5F3E907051C5B9" ++#define TEST2_LABEL "SSSD test cert 0002" + #define TEST5_KEY_ID "1195833C424AB00297F582FC43FFFFAB47A64CC9" ++#define TEST5_LABEL "SSSD test cert 0005" + + static char CACHED_AUTH_TIMEOUT_STR[] = "4"; + static const int CACHED_AUTH_TIMEOUT = 4; +@@ -673,6 +676,7 @@ static int test_pam_cert_check_gdm_smartcard(uint32_t status, uint8_t *body, + + sizeof(TEST_TOKEN_NAME) + + sizeof(TEST_MODULE_NAME) + + sizeof(TEST_KEY_ID) ++ + sizeof(TEST_LABEL) + + sizeof(TEST_PROMPT) + + sizeof("pamuser"))); + +@@ -692,6 +696,10 @@ static int test_pam_cert_check_gdm_smartcard(uint32_t status, uint8_t *body, + assert_string_equal(body + rp, TEST_KEY_ID); + rp += sizeof(TEST_KEY_ID); + ++ assert_int_equal(*(body + rp + sizeof(TEST_LABEL) - 1), 0); ++ assert_string_equal(body + rp, TEST_LABEL); ++ rp += sizeof(TEST_LABEL); ++ + assert_int_equal(*(body + rp + sizeof(TEST_PROMPT) - 1), 0); + assert_string_equal(body + rp, TEST_PROMPT); + rp += sizeof(TEST_PROMPT); +@@ -740,6 +748,7 @@ static int test_pam_cert_check_ex(uint32_t status, uint8_t *body, size_t blen, + TEST_TOKEN_NAME, + TEST_MODULE_NAME, + TEST_KEY_ID, ++ TEST_LABEL, + TEST_PROMPT, + NULL, + NULL }; +@@ -749,6 +758,7 @@ static int test_pam_cert_check_ex(uint32_t status, uint8_t *body, size_t blen, + TEST_TOKEN_NAME, + TEST_MODULE_NAME, + TEST2_KEY_ID, ++ TEST2_LABEL, + TEST2_PROMPT, + NULL, + NULL }; +@@ -756,10 +766,10 @@ static int test_pam_cert_check_ex(uint32_t status, uint8_t *body, size_t blen, + assert_int_equal(status, 0); + + check_strings[0] = name; +- check_strings[5] = nss_name; ++ check_strings[6] = nss_name; + check_len = check_string_array_len(check_strings); + check2_strings[0] = name; +- check2_strings[5] = nss_name; ++ check2_strings[6] = nss_name; + check2_len = check_string_array_len(check2_strings); + + +@@ -843,6 +853,7 @@ static int test_pam_cert2_token2_check_ex(uint32_t status, uint8_t *body, + TEST_TOKEN2_NAME, + TEST_MODULE_NAME, + TEST2_KEY_ID, ++ TEST2_LABEL, + TEST2_PROMPT, + NULL, + NULL }; +@@ -850,7 +861,7 @@ static int test_pam_cert2_token2_check_ex(uint32_t status, uint8_t *body, + assert_int_equal(status, 0); + + check2_strings[0] = name; +- check2_strings[5] = nss_name; ++ check2_strings[6] = nss_name; + check2_len = check_string_array_len(check2_strings); + + SAFEALIGN_COPY_UINT32(&val, body + rp, &rp); +@@ -895,7 +906,7 @@ static int test_pam_cert_X_token_X_check_ex(uint32_t status, uint8_t *body, + assert_int_equal(status, 0); + + check_strings[0] = name; +- check_strings[5] = nss_name; ++ check_strings[6] = nss_name; + check_len = check_string_array_len(check_strings); + + SAFEALIGN_COPY_UINT32(&val, body + rp, &rp); +@@ -946,6 +957,7 @@ static int test_pam_cert5_check(uint32_t status, uint8_t *body, size_t blen) + TEST_TOKEN_NAME, + TEST_MODULE_NAME, + TEST5_KEY_ID, ++ TEST5_LABEL, + TEST5_PROMPT, + NULL, + NULL }; +-- +2.21.3 + diff --git a/SOURCES/0016-add-tests-multiple-certs-same-id.patch b/SOURCES/0016-add-tests-multiple-certs-same-id.patch new file mode 100644 index 0000000..cd9cefd --- /dev/null +++ b/SOURCES/0016-add-tests-multiple-certs-same-id.patch @@ -0,0 +1,265 @@ +From f633f37e712cb0f7524a2ee257e15f34468149b4 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Tue, 3 Nov 2020 09:58:52 +0100 +Subject: [PATCH 16/16] add tests multiple certs same id + +Add unit test for the case that two certificates use the same key. + +Resolves: https://github.com/SSSD/sssd/issues/5400 + +Reviewed-by: Alexey Tikhonov +--- + src/tests/cmocka/test_pam_srv.c | 116 +++++++++++++++++++ + src/tests/test_CA/Makefile.am | 26 ++++- + src/tests/test_CA/SSSD_test_cert_0006.config | 20 ++++ + 3 files changed, 161 insertions(+), 1 deletion(-) + create mode 100644 src/tests/test_CA/SSSD_test_cert_0006.config + +diff --git a/src/tests/cmocka/test_pam_srv.c b/src/tests/cmocka/test_pam_srv.c +index 5506fbf34..8ca5abd43 100644 +--- a/src/tests/cmocka/test_pam_srv.c ++++ b/src/tests/cmocka/test_pam_srv.c +@@ -40,12 +40,14 @@ + #include "tests/test_CA/SSSD_test_cert_x509_0001.h" + #include "tests/test_CA/SSSD_test_cert_x509_0002.h" + #include "tests/test_CA/SSSD_test_cert_x509_0005.h" ++#include "tests/test_CA/SSSD_test_cert_x509_0006.h" + + #include "tests/test_ECC_CA/SSSD_test_ECC_cert_x509_0001.h" + #else + #define SSSD_TEST_CERT_0001 "" + #define SSSD_TEST_CERT_0002 "" + #define SSSD_TEST_CERT_0005 "" ++#define SSSD_TEST_CERT_0006 "" + + #define SSSD_TEST_ECC_CERT_0001 "" + #endif +@@ -1093,6 +1095,13 @@ static int test_pam_creds_insufficient_check(uint32_t status, + return EOK; + } + ++static int test_pam_auth_err_check(uint32_t status, uint8_t *body, size_t blen) ++{ ++ /* PAM_AUTH_ERR is returned for different types of error, we use different ++ * names for the check functions to make the purpose more clear. */ ++ return test_pam_wrong_pw_offline_auth_check(status, body, blen); ++} ++ + static int test_pam_user_unknown_check(uint32_t status, + uint8_t *body, size_t blen) + { +@@ -2500,6 +2509,107 @@ void test_pam_cert_auth_2certs_one_mapping(void **state) + assert_int_equal(ret, EOK); + } + ++/* The following three tests cover a use case where multiple certificates are ++ * using the same key-pair. According to PKCS#11 specs "The CKA_ID field is ++ * intended to distinguish among multiple keys. In the case of public and ++ * private keys, this field assists in handling multiple keys held by the same ++ * subject; the key identifier for a public key and its corresponding private ++ * key should be the same. The key identifier should also be the same as for ++ * the corresponding certificate, if one exists. Cryptoki does not enforce ++ * these associations, however." As a result certificates sharing the same ++ * key-pair will have the same id on the Smartcard. This means a second ++ * parameter is needed to distinguish them. We use the label here. ++ * ++ * The first test makes sure authentication fails is the label is missing, the ++ * second and third test make sure that each certificate can be selected with ++ * the proper label. */ ++void test_pam_cert_auth_2certs_same_id_no_label(void **state) ++{ ++ int ret; ++ ++ set_cert_auth_param(pam_test_ctx->pctx, CA_DB); ++ putenv(discard_const("SOFTHSM2_CONF=" ABS_BUILD_DIR "/src/tests/test_CA/softhsm2_2certs_same_id.conf")); ++ ++ mock_input_pam_cert(pam_test_ctx, "pamuser", "123456", "SSSD Test Token", ++ TEST_MODULE_NAME, ++ "11111111", ++ NULL, NULL, ++ NULL, SSSD_TEST_CERT_0001); ++ ++ will_return(__wrap_sss_packet_get_cmd, SSS_PAM_AUTHENTICATE); ++ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); ++ ++ /* Assume backend cannot handle Smartcard credentials */ ++ pam_test_ctx->exp_pam_status = PAM_BAD_ITEM; ++ ++ set_cmd_cb(test_pam_auth_err_check); ++ ret = sss_cmd_execute(pam_test_ctx->cctx, SSS_PAM_AUTHENTICATE, ++ pam_test_ctx->pam_cmds); ++ assert_int_equal(ret, EOK); ++ ++ /* Wait until the test finishes with EOK */ ++ ret = test_ev_loop(pam_test_ctx->tctx); ++ assert_int_equal(ret, EOK); ++} ++ ++void test_pam_cert_auth_2certs_same_id_with_label_1(void **state) ++{ ++ int ret; ++ ++ set_cert_auth_param(pam_test_ctx->pctx, CA_DB); ++ putenv(discard_const("SOFTHSM2_CONF=" ABS_BUILD_DIR "/src/tests/test_CA/softhsm2_2certs_same_id.conf")); ++ ++ mock_input_pam_cert(pam_test_ctx, "pamuser", "123456", "SSSD Test Token", ++ TEST_MODULE_NAME, ++ "11111111", ++ "SSSD test cert 0001", NULL, ++ test_lookup_by_cert_double_cb, SSSD_TEST_CERT_0001); ++ ++ will_return(__wrap_sss_packet_get_cmd, SSS_PAM_AUTHENTICATE); ++ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); ++ ++ /* Assume backend cannot handle Smartcard credentials */ ++ pam_test_ctx->exp_pam_status = PAM_BAD_ITEM; ++ ++ set_cmd_cb(test_pam_simple_check_success); ++ ret = sss_cmd_execute(pam_test_ctx->cctx, SSS_PAM_AUTHENTICATE, ++ pam_test_ctx->pam_cmds); ++ assert_int_equal(ret, EOK); ++ ++ /* Wait until the test finishes with EOK */ ++ ret = test_ev_loop(pam_test_ctx->tctx); ++ assert_int_equal(ret, EOK); ++} ++ ++void test_pam_cert_auth_2certs_same_id_with_label_6(void **state) ++{ ++ int ret; ++ ++ set_cert_auth_param(pam_test_ctx->pctx, CA_DB); ++ putenv(discard_const("SOFTHSM2_CONF=" ABS_BUILD_DIR "/src/tests/test_CA/softhsm2_2certs_same_id.conf")); ++ ++ mock_input_pam_cert(pam_test_ctx, "pamuser", "123456", "SSSD Test Token", ++ TEST_MODULE_NAME, ++ "11111111", ++ "SSSD test cert 0006", NULL, ++ test_lookup_by_cert_double_cb, SSSD_TEST_CERT_0006); ++ ++ will_return(__wrap_sss_packet_get_cmd, SSS_PAM_AUTHENTICATE); ++ will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); ++ ++ /* Assume backend cannot handle Smartcard credentials */ ++ pam_test_ctx->exp_pam_status = PAM_BAD_ITEM; ++ ++ set_cmd_cb(test_pam_simple_check_success); ++ ret = sss_cmd_execute(pam_test_ctx->cctx, SSS_PAM_AUTHENTICATE, ++ pam_test_ctx->pam_cmds); ++ assert_int_equal(ret, EOK); ++ ++ /* Wait until the test finishes with EOK */ ++ ret = test_ev_loop(pam_test_ctx->tctx); ++ assert_int_equal(ret, EOK); ++} ++ + void test_pam_cert_preauth_uri_token1(void **state) + { + int ret; +@@ -3179,6 +3289,12 @@ int main(int argc, const char *argv[]) + pam_test_setup, pam_test_teardown), + cmocka_unit_test_setup_teardown(test_pam_cert_auth_2certs_one_mapping, + pam_test_setup, pam_test_teardown), ++ cmocka_unit_test_setup_teardown(test_pam_cert_auth_2certs_same_id_no_label, ++ pam_test_setup, pam_test_teardown), ++ cmocka_unit_test_setup_teardown(test_pam_cert_auth_2certs_same_id_with_label_1, ++ pam_test_setup, pam_test_teardown), ++ cmocka_unit_test_setup_teardown(test_pam_cert_auth_2certs_same_id_with_label_6, ++ pam_test_setup, pam_test_teardown), + cmocka_unit_test_setup_teardown(test_pam_cert_auth_no_logon_name, + pam_test_setup, pam_test_teardown), + cmocka_unit_test_setup_teardown(test_pam_cert_auth_no_logon_name_no_key_id, +diff --git a/src/tests/test_CA/Makefile.am b/src/tests/test_CA/Makefile.am +index 0e0122737..8765d0fd6 100644 +--- a/src/tests/test_CA/Makefile.am ++++ b/src/tests/test_CA/Makefile.am +@@ -6,6 +6,7 @@ dist_noinst_DATA = \ + SSSD_test_cert_0003.config \ + SSSD_test_cert_0004.config \ + SSSD_test_cert_0005.config \ ++ SSSD_test_cert_0006.config \ + SSSD_test_cert_key_0001.pem \ + SSSD_test_cert_key_0002.pem \ + SSSD_test_cert_key_0003.pem \ +@@ -25,7 +26,7 @@ pubkeys = $(addprefix SSSD_test_cert_pubsshkey_,$(addsuffix .pub,$(ids))) + pubkeys_h = $(addprefix SSSD_test_cert_pubsshkey_,$(addsuffix .h,$(ids))) + pkcs12 = $(addprefix SSSD_test_cert_pkcs12_,$(addsuffix .pem,$(ids))) + +-extra = softhsm2_none softhsm2_one softhsm2_two softhsm2_2tokens softhsm2_ocsp ++extra = softhsm2_none softhsm2_one softhsm2_two softhsm2_2tokens softhsm2_ocsp softhsm2_2certs_same_id + if HAVE_FAKETIME + extra += SSSD_test_CA_expired_crl.pem + endif +@@ -41,6 +42,14 @@ $(pwdfile): + SSSD_test_CA.pem: $(openssl_ca_key) $(openssl_ca_config) serial + $(OPENSSL) req -batch -config ${openssl_ca_config} -x509 -new -nodes -key $< -sha256 -days 1024 -set_serial 0 -extensions v3_ca -out $@ + ++# SSSD_test_cert_0006 should use the same key as SSSD_test_cert_0001 ++.INTERMEDIATE: SSSD_test_cert_req_0006.pem ++SSSD_test_cert_req_0006.pem: $(srcdir)/SSSD_test_cert_key_0001.pem $(srcdir)/SSSD_test_cert_0006.config ++ if [ $(shell grep -c req_exts $(srcdir)/SSSD_test_cert_0006.config) -eq 0 ]; then \ ++ $(OPENSSL) req -new -nodes -key $< -config $(srcdir)/SSSD_test_cert_0006.config -out $@ ; \ ++ else \ ++ $(OPENSSL) req -new -nodes -key $< -reqexts req_exts -config $(srcdir)/SSSD_test_cert_0006.config -out $@ ; \ ++ fi + + SSSD_test_cert_req_%.pem: $(srcdir)/SSSD_test_cert_key_%.pem $(srcdir)/SSSD_test_cert_%.config + if [ $(shell grep -c req_exts $(srcdir)/SSSD_test_cert_$*.config) -eq 0 ]; then \ +@@ -52,6 +61,9 @@ SSSD_test_cert_req_%.pem: $(srcdir)/SSSD_test_cert_key_%.pem $(srcdir)/SSSD_test + SSSD_test_cert_x509_%.pem: SSSD_test_cert_req_%.pem $(openssl_ca_config) SSSD_test_CA.pem + $(OPENSSL) ca -config ${openssl_ca_config} -batch -notext -keyfile $(openssl_ca_key) -in $< -days 200 -extensions usr_cert -out $@ + ++SSSD_test_cert_pkcs12_0006.pem: SSSD_test_cert_x509_0006.pem $(srcdir)/SSSD_test_cert_key_0001.pem $(pwdfile) ++ $(OPENSSL) pkcs12 -export -in SSSD_test_cert_x509_0006.pem -inkey $(srcdir)/SSSD_test_cert_key_0001.pem -nodes -passout file:$(pwdfile) -out $@ ++ + SSSD_test_cert_pkcs12_%.pem: SSSD_test_cert_x509_%.pem $(srcdir)/SSSD_test_cert_key_%.pem $(pwdfile) + $(OPENSSL) pkcs12 -export -in SSSD_test_cert_x509_$*.pem -inkey $(srcdir)/SSSD_test_cert_key_$*.pem -nodes -passout file:$(pwdfile) -out $@ + +@@ -130,6 +142,18 @@ softhsm2_ocsp.conf: + @echo "objectstore.backend = file" >> $@ + @echo "slots.removable = true" >> $@ + ++softhsm2_2certs_same_id: softhsm2_2certs_same_id.conf SSSD_test_cert_x509_0001.pem SSSD_test_cert_x509_0006.pem ++ mkdir $@ ++ SOFTHSM2_CONF=./$< $(SOFTHSM2_UTIL) --init-token --label "SSSD Test Token" --pin 123456 --so-pin 123456 --free ++ GNUTLS_PIN=123456 SOFTHSM2_CONF=./$< $(P11TOOL) --provider=$(SOFTHSM2_PATH) --write --no-mark-private --load-certificate=SSSD_test_cert_x509_0006.pem --login --label 'SSSD test cert 0006' --id '11111111' ++ GNUTLS_PIN=123456 SOFTHSM2_CONF=./$< $(P11TOOL) --provider=$(SOFTHSM2_PATH) --write --no-mark-private --load-certificate=SSSD_test_cert_x509_0001.pem --login --label 'SSSD test cert 0001' --id '11111111' ++ GNUTLS_PIN=123456 SOFTHSM2_CONF=./$< $(P11TOOL) --provider=$(SOFTHSM2_PATH) --write --load-privkey=$(srcdir)/SSSD_test_cert_key_0001.pem --login --label 'SSSD test cert 0001' --id '11111111' ++ ++softhsm2_2certs_same_id.conf: ++ @echo "directories.tokendir = "$(abs_top_builddir)"/src/tests/test_CA/softhsm2_2certs_same_id" > $@ ++ @echo "objectstore.backend = file" >> $@ ++ @echo "slots.removable = true" >> $@ ++ + CLEANFILES = \ + index.txt index.txt.attr \ + index.txt.attr.old index.txt.old \ +diff --git a/src/tests/test_CA/SSSD_test_cert_0006.config b/src/tests/test_CA/SSSD_test_cert_0006.config +new file mode 100644 +index 000000000..762de55cd +--- /dev/null ++++ b/src/tests/test_CA/SSSD_test_cert_0006.config +@@ -0,0 +1,20 @@ ++# This certificate is used in ++# - src/tests/cmocka/test_pam_srv.c ++# and should use the same key-pair as SSSD_test_cert_0001 ++[ req ] ++distinguished_name = req_distinguished_name ++prompt = no ++ ++[ req_distinguished_name ] ++O = SSSD ++OU = SSSD test ++CN = SSSD test cert 0006 ++ ++[ req_exts ] ++basicConstraints = CA:FALSE ++nsCertType = client, email ++nsComment = "SSSD test Certificate" ++subjectKeyIdentifier = hash ++keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment ++extendedKeyUsage = clientAuth, emailProtection ++subjectAltName = email:sssd-devel@lists.fedorahosted.org,URI:https://github.com/SSSD/sssd// +-- +2.21.3 + diff --git a/SOURCES/0017-data_provider_be-Add-random-offset-default.patch b/SOURCES/0017-data_provider_be-Add-random-offset-default.patch new file mode 100644 index 0000000..7574eec --- /dev/null +++ b/SOURCES/0017-data_provider_be-Add-random-offset-default.patch @@ -0,0 +1,53 @@ +From 1e9abd508ea5627465d528788645d4dbe53d7d31 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pawe=C5=82=20Po=C5=82awski?= +Date: Wed, 2 Dec 2020 03:00:26 +0100 +Subject: [PATCH 17/18] data_provider_be: Add random offset default + +Replace hardcoded default value of 30 with more meaningful +OFFLINE_TIMEOUT_RANDOM_OFFSET define. + +This value is used to calculate task timeout during offline +status checking by formula (from SSSD MAN page): + +new_interval = (old_interval * 2) + random_offset + +As it is explicite mentioned in documentation it should +be expressed in the code similar way. + +Reviewed-by: Iker Pedrosa +--- + src/providers/data_provider_be.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c +index 4c10d6b48..10421c6b4 100644 +--- a/src/providers/data_provider_be.c ++++ b/src/providers/data_provider_be.c +@@ -51,6 +51,7 @@ + #define ONLINE_CB_RETRY 3 + #define ONLINE_CB_RETRY_MAX_DELAY 4 + ++#define OFFLINE_TIMEOUT_RANDOM_OFFSET 30 + #define OFFLINE_TIMEOUT_DEFAULT 60 + #define OFFLINE_TIMEOUT_MAX_DEFAULT 3600 + +@@ -152,9 +153,13 @@ void be_mark_offline(struct be_ctx *ctx) + offline_timeout = get_offline_timeout(ctx); + offline_timeout_max = get_offline_timeout_max(ctx); + +- ret = be_ptask_create_sync(ctx, ctx, +- offline_timeout, offline_timeout, +- offline_timeout, 30, offline_timeout, ++ ret = be_ptask_create_sync(ctx, ++ ctx, ++ offline_timeout, ++ offline_timeout, ++ offline_timeout, ++ OFFLINE_TIMEOUT_RANDOM_OFFSET, ++ offline_timeout, + offline_timeout_max, + try_to_go_online, + ctx, "Check if online (periodic)", +-- +2.21.3 + diff --git a/SOURCES/0018-data_provider_be-MAN-page-update.patch b/SOURCES/0018-data_provider_be-MAN-page-update.patch new file mode 100644 index 0000000..15e4168 --- /dev/null +++ b/SOURCES/0018-data_provider_be-MAN-page-update.patch @@ -0,0 +1,59 @@ +From 171b664ec4a7c94583b35597bd7e1e72bf89d217 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pawe=C5=82=20Po=C5=82awski?= +Date: Wed, 2 Dec 2020 03:10:50 +0100 +Subject: [PATCH 18/18] data_provider_be: MAN page update + +Updated description of parameters: +* offline_timeout +* offline_timeout_max + +MAN page now explains that in some circumstances +corelation of offline_timeout and offline_timeout_max values +may lead to offline checking interval not incrementing. +This is a false positive error as in fact the value +just saturates almost instantly. + +Reviewed-by: Iker Pedrosa +--- + src/man/sssd.conf.5.xml | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml +index d637e2eaa..8b330de58 100644 +--- a/src/man/sssd.conf.5.xml ++++ b/src/man/sssd.conf.5.xml +@@ -739,12 +739,12 @@ + offline_timeout + random_offset + + +- The random offset can increment up to 30 seconds. ++ The random offset value is from 0 to 30. + After each unsuccessful attempt to go online, + the new interval is recalculated by the following: + + +- new_interval = old_interval*2 + random_offset ++ new_interval = (old_interval * 2) + random_offset + + + Note that the maximum length of each interval +@@ -769,6 +769,16 @@ + + A value of 0 disables the incrementing behaviour. + ++ ++ The value of this parameter should be set in correlation ++ to offline_timeout parameter value. ++ ++ ++ With offline_timeout set to 60 (default value) there is no point ++ in setting offlinet_timeout_max to less than 120 as it will ++ saturate instantly. General rule here should be to set ++ offline_timeout_max to at least 4 times offline_timeout. ++ + + Although a value between 0 and offline_timeout may be + specified, it has the effect of overriding the +-- +2.21.3 + diff --git a/SOURCES/0019-logs-review.patch b/SOURCES/0019-logs-review.patch new file mode 100644 index 0000000..54fc132 --- /dev/null +++ b/SOURCES/0019-logs-review.patch @@ -0,0 +1,3410 @@ +From 69ef1cf763fca6b2c7174ddacf3f510c73cc27e6 Mon Sep 17 00:00:00 2001 +From: Alexey Tikhonov +Date: Mon, 28 Dec 2020 19:36:48 +0100 +Subject: [PATCH] Squashed commit of the following: + +commit bd2f38abe95645b9b16b12d12dac6008b0d2a03b +Author: Alexey Tikhonov +Date: Tue Dec 15 18:47:25 2020 +0100 + + UTIL: find_domain_by_object_name_ex() changed log level + + It's up to user of this function to judge if fail to parse fqname is + a critical error. + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit 0db68a1f95612fcbad18ca8107a4b170f446dd59 +Author: Alexey Tikhonov +Date: Tue Dec 15 17:26:09 2020 +0100 + + LDAP: sdap_save_grpmem(): log level changed + + There are legitimate reasons when sdap_save_grpmem() can be called + with `ignore_group_members = true` + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit 00e3ac4a4f9b6c8da27daa3ed8c18664c99256bb +Author: Alexey Tikhonov +Date: Sun Dec 13 23:21:37 2020 +0100 + + LDAP: reduce log level in case of fail to store members of missing group (it might be built-in skipped intentionally) + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit dba7de0db3cbaee43ef06a1b7c847fbcf48f3708 +Author: Alexey Tikhonov +Date: Sun Dec 13 22:37:44 2020 +0100 + + SYSDB: changed logging in sysdb_get_real_name() + + Missing cache entry isn't an error. + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit e86599ba079611ed324ff1493a7173d11c1a7961 +Author: Alexey Tikhonov +Date: Sun Dec 13 22:22:36 2020 +0100 + + IPA: changed logging in ipa_get_subdom_acct_send() + + Frontends do not know what kind of lookup the backends support + so it is expected that they might send unsupported requests. + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit bf873598a9d4ac8256b20859c0d92fb509861b6b +Author: Alexey Tikhonov +Date: Sun Dec 13 20:29:07 2020 +0100 + + IPA: ignore failed group search in certain cases + + It's currently expected to see those messages with sudo or HBAC rules in play. + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit 60b17be9e4f4865fe1774076808a6c783a7ec906 +Author: Alexey Tikhonov +Date: Sun Dec 13 19:36:56 2020 +0100 + + SYSDB: changed log level in sysdb_update_members_ex() + + Fail to add already existing member isn't critical. + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit 9390af3c2d1b33e2b5ded0ea0c6c436b9776cedc +Author: Alexey Tikhonov +Date: Sat Dec 12 21:29:06 2020 +0100 + + IPA: reduce log level in apply_subdomain_homedir() + + Missing UID for SYSDB_GROUP_CLASS is not an error + (see commit message of e66517dcf63f1d4aaf866c22371dac7740ce0a48 for + additional details) + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit 9215cf4e2519d5f085bf97f26a74d499090e46e1 +Author: Alexey Tikhonov +Date: Sat Dec 12 20:46:40 2020 +0100 + + CERTMAP: removed stray debug message + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit 0986cf6ced8c4e09b8031d19eddffca679aca30c +Author: Alexey Tikhonov +Date: Thu Dec 3 21:06:31 2020 +0100 + + UTIL: fixed bug in server_setup() that prevented setting debug level to 0 explicitly + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit 644453f8d93540a91236683015f3418d29c6d95a +Author: Alexey Tikhonov +Date: Tue Dec 1 13:03:03 2020 +0100 + + LOGS: default log level changed to <= SSSDBG_OP_FAILURE + + :config: New default value of `debug_level` is 0x0070 + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit 4fe060abbe958c2f9b5aa44e489620063029aa0b +Author: Alexey Tikhonov +Date: Mon Nov 30 22:19:46 2020 +0100 + + FILES: reduced debug level in refresh_override_attrs() if case "No overrides, nothing to do" + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit 29f243fd5b256efe3c7f4e4f0940c7d0ae6b4fa1 +Author: Alexey Tikhonov +Date: Mon Nov 30 22:07:01 2020 +0100 + + AD: reduced log level in case check_if_pac_is_available() can't find user entry. This is typical situation when, for example, INITGROUPS lookup is executed for uncached user. + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit ed6ec569780ad8203c4990faed5a9f0dc27dd12b +Author: Alexey Tikhonov +Date: Mon Nov 30 21:13:28 2020 +0100 + + SDAP: reduced log level in case group without members + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit 26fdc3c8f0ae6493442ea291d9bf36ba148ef209 +Author: Alexey Tikhonov +Date: Mon Nov 30 21:06:19 2020 +0100 + + CACHE_REQ: reduced log level in cache_req_object_by_name_well_known() Non fqdn input isn't necessarily an error here. + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit a7b145b99b9f71ad3d02251fff5b587041c9f1ab +Author: Alexey Tikhonov +Date: Mon Nov 30 20:27:44 2020 +0100 + + LDAP: reduced log level in hosts_get_done() + + Absent host in LDAP server isn't SSSD failure. + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit 6e3b4d745fc8d2de14d69aa30bc21aa549a435f8 +Author: Alexey Tikhonov +Date: Mon Nov 30 16:45:51 2020 +0100 + + SBUS: reduced log level in case of unexpected signal + + Most probably module is not fully initialized yet. + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit 90dae38d7442757b8a51f91a6ba3fb83f99320a1 +Author: Alexey Tikhonov +Date: Mon Nov 30 11:39:56 2020 +0100 + + RESPONDER: reduce log level in sss_parse_inp_done() in case of "Unknown domain" since this might be search by UPN + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit 69aa3e8c4b82a06e45ba59eb1c17af252aa971ce +Author: Alexey Tikhonov +Date: Mon Nov 30 01:05:52 2020 +0100 + + DP: do not log failure in case provider doesn't support check_online method + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit 1af89925e62cccacb2957f55b16988a5e71fe5e1 +Author: Alexey Tikhonov +Date: Mon Nov 30 00:28:08 2020 +0100 + + IPA: corrected confusing message + + Log message like: + ``` + sysdb_getpwnam() got more users than expected. Expected [1], got [0] + ``` + looks a bit confusing. + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit a419b7e673d2de571d873b79be31b1ae2fa89832 +Author: Alexey Tikhonov +Date: Mon Nov 30 00:13:31 2020 +0100 + + SSS_IFACE: corrected misleading return code + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit 99e44d9db41f5bb56281ed65d815c32139195931 +Author: Alexey Tikhonov +Date: Sun Nov 29 22:55:07 2020 +0100 + + LDAP: added missed \n in log message + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit 52dc85540e621b00f358fea94e2e390d580948d8 +Author: Alexey Tikhonov +Date: Sun Nov 29 21:42:08 2020 +0100 + + SYSDB: reduce log level in sysdb_update_members_ex() in case failed attempt to DEL unexisting attribute + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit a7b6413d9fb870f51f09955bdceee01952442c63 +Author: Alexey Tikhonov +Date: Sun Nov 29 21:32:46 2020 +0100 + + UTIL: sss_ldb_error_to_errno() improved + + LDB_ERR_NO_SUCH_ATTRIBUTE error code was added to mapping and log level + for unknown error code was reduced. + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit ac22859006b5658017b2720ca3e02d34c5beecdd +Author: Alexey Tikhonov +Date: Sun Nov 29 17:03:58 2020 +0100 + + PAM: reduce log level in may_do_cert_auth() + + Reduce log level in may_do_cert_auth() as this is not a critical failure + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit 5068655a67f88cb1730f28689c5effee264321ad +Author: Alexey Tikhonov +Date: Fri Nov 27 21:45:53 2020 +0100 + + UTIL: few debug message corrections + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit 3cbd0465b52f9bbb7e20b0b12e154f51bab0866e +Author: Alexey Tikhonov +Date: Fri Nov 27 21:12:16 2020 +0100 + + PAM: few debug message corrections + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit f028253ff87bf11ed034ad5acf1f67e8863bed60 +Author: Alexey Tikhonov +Date: Fri Nov 27 20:59:13 2020 +0100 + + NSS: few debug message corrections + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit f457a1a69240381ad7637a09dc66c1aeb78e1d18 +Author: Alexey Tikhonov +Date: Fri Nov 27 20:33:11 2020 +0100 + + IFP: few debug message corrections + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit 058644f2ef6d1958db657d371158d2df7798dd49 +Author: Alexey Tikhonov +Date: Fri Nov 27 20:21:55 2020 +0100 + + RESPONDER: few debug message corrections + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit 01ba32f250a0e51771471c52440c11f6f05f2a48 +Author: Alexey Tikhonov +Date: Fri Nov 27 20:15:22 2020 +0100 + + CACHE_REQ: debug message correction + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit 018c08acbb3bbb836c9acefaf5c384eb9231a60a +Author: Alexey Tikhonov +Date: Fri Nov 27 20:05:06 2020 +0100 + + AUTOFS: few debug message corrections + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit fb052a4c9843ce518a7202d842c43631f8bbfd2d +Author: Alexey Tikhonov +Date: Fri Nov 27 19:57:00 2020 +0100 + + RESOLV: debug message correction + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit d91409df456f9ad7aad39d0cad0ed053cf1f3653 +Author: Alexey Tikhonov +Date: Fri Nov 27 19:49:14 2020 +0100 + + PROXY: few debug message corrections + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit ff8f44ce2d2eedb098d980793a949f7f7e55576a +Author: Alexey Tikhonov +Date: Fri Nov 20 19:46:28 2020 +0100 + + LDAP: few debug message corrections + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit 9244820af59ba6b947cf9aa1269d03bb6f2e4f38 +Author: Alexey Tikhonov +Date: Fri Nov 20 19:22:36 2020 +0100 + + KRB5: few debug message corrections + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit 667b983aaee380c50d50ef07542b004e60041581 +Author: Alexey Tikhonov +Date: Thu Nov 19 18:31:28 2020 +0100 + + IPA: few debug message corrections + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit 2f70695a874dcb84d4b86773138a5a6b6259958f +Author: Alexey Tikhonov +Date: Wed Nov 18 22:12:21 2020 +0100 + + DP: few debug message corrections + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit d6f6f053d7a97a220b52ce92fd653eef8cec5a74 +Author: Alexey Tikhonov +Date: Wed Nov 18 21:37:38 2020 +0100 + + AD: few debug message corrections + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit 85d8adc4d24f09e47f2a9c0fa595d90c61036b18 +Author: Alexey Tikhonov +Date: Wed Nov 18 19:09:33 2020 +0100 + + P11_CHILD: severity level of few debug messages adjusted + + Severity level of few debug messages was adjusted and journal message + in case of disabled certificate verification was added. + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit fe0530ef96baa8fd39ce6b87c0c760e17c5eb6f8 +Author: Alexey Tikhonov +Date: Wed Nov 18 16:28:43 2020 +0100 + + MONITOR: severity level of few debug messages adjusted + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit daa5454f870a5436a554091a1333cc8be0cbc566 +Author: Alexey Tikhonov +Date: Wed Nov 18 16:02:23 2020 +0100 + + SYSDB:views: few debug message corrections + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit 82dc14b027f9115cabafce71d2b385d5c7d1dd4f +Author: Alexey Tikhonov +Date: Wed Nov 18 15:56:46 2020 +0100 + + SYSDB:upgrade: debug message corrected + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit e731368ed9cea9b35d0ae654e1534084c6ef4642 +Author: Alexey Tikhonov +Date: Wed Nov 18 15:50:08 2020 +0100 + + SYSDB:service: severity level of few debug messages adjusted + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit f55c9599068c43037a8b666af92ba9b8a044f735 +Author: Alexey Tikhonov +Date: Wed Nov 18 15:32:21 2020 +0100 + + SYSDB:selinux: debug message severity level was adjusted + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit 744582419abfd6e5665315748d44e732f1d56f13 +Author: Alexey Tikhonov +Date: Wed Nov 18 15:30:45 2020 +0100 + + SYSDB:search: few debug messages were corrected + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit 033c31a2a4994367edea1ded8303a0d2dbc59b1c +Author: Alexey Tikhonov +Date: Wed Nov 18 15:19:46 2020 +0100 + + SYSDB:ops: few debug messages were corrected + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit a73df70ee0bcc8f1b80a2e20132592724bd5f675 +Author: Alexey Tikhonov +Date: Wed Nov 18 13:19:25 2020 +0100 + + SYSDB:ipnetworks: severity level of few debug messages adjusted + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit b4acf71d0a81aeeb2754645d2798ce1e927121f3 +Author: Alexey Tikhonov +Date: Mon Nov 16 21:18:14 2020 +0100 + + SYSDB:iphosts: severity level of few debug messages adjusted + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit d8af1db84b48193a546bbeec84a7dd7e2b132244 +Author: Alexey Tikhonov +Date: Mon Nov 16 20:05:12 2020 +0100 + + SYSDB:sudo: changed debug message to be consistent + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit df723cb98b406b0262f04d0e43e8e5bf0030074f +Author: Alexey Tikhonov +Date: Mon Nov 16 19:10:41 2020 +0100 + + SYSDB: wrong debug message corrected + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose + +commit e350d917e6d48c1d13502ab2849d3e2a0815215e +Author: Alexey Tikhonov +Date: Mon Nov 16 18:13:26 2020 +0100 + + SYSDB:autofs: cosmetic updates + + Reviewed-by: Pawel Polawski + Reviewed-by: Sumit Bose +--- + src/db/sysdb.c | 2 +- + src/db/sysdb_autofs.c | 4 +- + src/db/sysdb_iphosts.c | 10 ++--- + src/db/sysdb_ipnetworks.c | 6 +-- + src/db/sysdb_ops.c | 37 ++++++++++++------ + src/db/sysdb_search.c | 17 ++++++--- + src/db/sysdb_selinux.c | 2 +- + src/db/sysdb_services.c | 6 +-- + src/db/sysdb_sudo.c | 3 +- + src/db/sysdb_upgrade.c | 2 +- + src/db/sysdb_views.c | 6 +-- + src/lib/certmap/sss_certmap_krb5_match.c | 1 - + src/man/include/debug_levels.xml | 3 +- + src/man/include/debug_levels_tools.xml | 3 +- + src/monitor/monitor.c | 14 +++---- + src/p11_child/p11_child_common.c | 2 +- + src/p11_child/p11_child_common_utils.c | 3 ++ + src/p11_child/p11_child_openssl.c | 4 +- + src/providers/ad/ad_cldap_ping.c | 2 +- + src/providers/ad/ad_common.c | 7 ++-- + src/providers/ad/ad_dyndns.c | 6 +-- + src/providers/ad/ad_gpo.c | 16 +++++--- + src/providers/ad/ad_machine_pw_renewal.c | 7 ++-- + src/providers/ad/ad_pac.c | 6 ++- + src/providers/ad/ad_subdomains.c | 2 +- + src/providers/be_dyndns.c | 3 +- + src/providers/be_ptask.c | 2 +- + src/providers/be_refresh.c | 3 +- + src/providers/data_provider/dp.c | 4 +- + src/providers/data_provider/dp_target_sudo.c | 10 +++-- + src/providers/data_provider_be.c | 5 +-- + src/providers/data_provider_fo.c | 2 +- + src/providers/data_provider_opts.c | 6 +-- + src/providers/data_provider_req.h | 1 + + src/providers/files/files_ops.c | 2 +- + src/providers/ipa/ipa_access.c | 2 +- + src/providers/ipa/ipa_common.c | 5 +-- + src/providers/ipa/ipa_hbac_common.c | 2 +- + src/providers/ipa/ipa_hbac_services.c | 4 +- + src/providers/ipa/ipa_hbac_users.c | 4 +- + src/providers/ipa/ipa_id.c | 2 +- + src/providers/ipa/ipa_init.c | 4 +- + src/providers/ipa/ipa_s2n_exop.c | 3 +- + src/providers/ipa/ipa_selinux.c | 4 +- + src/providers/ipa/ipa_session.c | 4 +- + src/providers/ipa/ipa_subdomains_ext_groups.c | 3 +- + src/providers/ipa/ipa_subdomains_id.c | 38 +++++++++++++------ + src/providers/ipa/ipa_subdomains_server.c | 11 +++--- + src/providers/ipa/ipa_sudo.c | 14 +++---- + src/providers/ipa/ipa_sudo_async.c | 10 ++--- + src/providers/ipa/ipa_sudo_conversion.c | 6 +-- + src/providers/ipa/ipa_views.c | 4 +- + src/providers/krb5/krb5_access.c | 3 +- + src/providers/krb5/krb5_auth.c | 4 +- + src/providers/krb5/krb5_child.c | 25 ++++++------ + src/providers/krb5/krb5_child_handler.c | 4 +- + src/providers/krb5/krb5_common.c | 6 +-- + .../krb5/krb5_delayed_online_authentication.c | 4 +- + src/providers/krb5/krb5_renew_tgt.c | 4 +- + src/providers/krb5/krb5_utils.c | 2 +- + src/providers/ldap/ldap_auth.c | 12 +++--- + src/providers/ldap/ldap_child.c | 2 +- + src/providers/ldap/ldap_init.c | 4 +- + src/providers/ldap/ldap_options.c | 8 ++-- + src/providers/ldap/sdap.c | 28 +++++++++----- + src/providers/ldap/sdap_access.c | 11 +++--- + src/providers/ldap/sdap_async.c | 9 +++-- + src/providers/ldap/sdap_async_autofs.c | 2 +- + src/providers/ldap/sdap_async_connection.c | 6 +-- + src/providers/ldap/sdap_async_groups.c | 27 ++++++++----- + src/providers/ldap/sdap_async_initgroups.c | 6 ++- + src/providers/ldap/sdap_async_initgroups_ad.c | 2 +- + src/providers/ldap/sdap_async_sudo.c | 4 +- + src/providers/ldap/sdap_child_helpers.c | 6 +-- + src/providers/ldap/sdap_hostid.c | 2 +- + src/providers/ldap/sdap_id_op.c | 2 +- + src/providers/proxy/proxy_auth.c | 6 +-- + src/providers/proxy/proxy_child.c | 8 ++-- + src/providers/proxy/proxy_client.c | 2 +- + src/providers/proxy/proxy_id.c | 6 +-- + src/resolv/async_resolv.c | 2 +- + src/responder/autofs/autofssrv.c | 2 +- + src/responder/autofs/autofssrv_cmd.c | 6 +-- + src/responder/common/cache_req/cache_req.c | 2 +- + .../plugins/cache_req_object_by_name.c | 4 +- + src/responder/common/responder_common.c | 4 +- + src/responder/common/responder_get_domains.c | 2 +- + src/responder/common/responder_iface.c | 4 +- + src/responder/ifp/ifp_iface/ifp_iface.c | 2 +- + src/responder/ifp/ifpsrv.c | 8 ++-- + src/responder/ifp/ifpsrv_util.c | 2 +- + src/responder/nss/nss_cmd.c | 20 +++++----- + src/responder/nss/nss_iface.c | 4 +- + src/responder/nss/nss_protocol_netgr.c | 2 +- + src/responder/nss/nsssrv.c | 2 +- + src/responder/pam/pamsrv_cmd.c | 2 +- + src/responder/pam/pamsrv_p11.c | 4 +- + src/sbus/router/sbus_router_handler.c | 3 +- + src/sss_iface/sss_iface.c | 4 +- + src/util/child_common.c | 2 +- + src/util/debug.h | 4 +- + src/util/domain_info_utils.c | 2 +- + src/util/server.c | 15 +++++--- + src/util/sss_sockets.c | 2 +- + src/util/string_utils.c | 2 +- + src/util/util_errors.c | 3 +- + 106 files changed, 364 insertions(+), 279 deletions(-) + +diff --git a/src/db/sysdb.c b/src/db/sysdb.c +index d0052d99b..d78991e36 100644 +--- a/src/db/sysdb.c ++++ b/src/db/sysdb.c +@@ -1489,7 +1489,7 @@ errno_t sysdb_attrs_primary_name(struct sysdb_ctx *sysdb, + * decide which name is correct. + */ + DEBUG(SSSDBG_CRIT_FAILURE, +- "Cannot save entry. Unable to determine groupname\n"); ++ "Can't match the name to the RDN\n"); + ret = EINVAL; + goto done; + } +diff --git a/src/db/sysdb_autofs.c b/src/db/sysdb_autofs.c +index 413b00722..1febdaec5 100644 +--- a/src/db/sysdb_autofs.c ++++ b/src/db/sysdb_autofs.c +@@ -243,14 +243,14 @@ sysdb_get_map_byname(TALLOC_CTX *mem_ctx, + "Error looking up autofs map [%s]\n", safe_map_name); + goto done; + } else if (ret == ENOENT) { +- DEBUG(SSSDBG_TRACE_FUNC, "No such map\n"); ++ DEBUG(SSSDBG_TRACE_FUNC, "No such map [%s]\n", safe_map_name); + *_map = NULL; + goto done; + } + + if (count != 1) { + DEBUG(SSSDBG_CRIT_FAILURE, +- "More than one map named %s\n", safe_map_name); ++ "More than one map named [%s]\n", safe_map_name); + goto done; + } + +diff --git a/src/db/sysdb_iphosts.c b/src/db/sysdb_iphosts.c +index b82279787..d3ee8f1a9 100644 +--- a/src/db/sysdb_iphosts.c ++++ b/src/db/sysdb_iphosts.c +@@ -222,14 +222,14 @@ sysdb_store_host(struct sss_domain_info *domain, + * sort it out. + */ + for (j = 0; j < res->count; j++) { +- DEBUG(SSSDBG_TRACE_FUNC, ++ DEBUG(SSSDBG_CRIT_FAILURE, + "Corrupt cache entry [%s] detected. Deleting\n", + ldb_dn_canonical_string(tmp_ctx, + res->msgs[j]->dn)); + + ret = sysdb_delete_entry(sysdb, res->msgs[j]->dn, true); + if (ret != EOK) { +- DEBUG(SSSDBG_MINOR_FAILURE, ++ DEBUG(SSSDBG_OP_FAILURE, + "Could not delete corrupt cache entry [%s]\n", + ldb_dn_canonical_string(tmp_ctx, + res->msgs[j]->dn)); +@@ -262,7 +262,7 @@ sysdb_store_host(struct sss_domain_info *domain, + + ret = sysdb_delete_entry(sysdb, res->msgs[0]->dn, true); + if (ret != EOK) { +- DEBUG(SSSDBG_MINOR_FAILURE, ++ DEBUG(SSSDBG_OP_FAILURE, + "Could not delete cache entry [%s]\n", + ldb_dn_canonical_string(tmp_ctx, + res->msgs[0]->dn)); +@@ -298,7 +298,7 @@ sysdb_store_host(struct sss_domain_info *domain, + + ret = sysdb_delete_entry(sysdb, res->msgs[i]->dn, true); + if (ret != EOK) { +- DEBUG(SSSDBG_MINOR_FAILURE, ++ DEBUG(SSSDBG_OP_FAILURE, + "Could not delete corrupt cache entry [%s]\n", + ldb_dn_canonical_string(tmp_ctx, + res->msgs[i]->dn)); +@@ -318,7 +318,7 @@ sysdb_store_host(struct sss_domain_info *domain, + /* Delete the entry from the previous pass */ + ret = sysdb_delete_entry(sysdb, update_dn, true); + if (ret != EOK) { +- DEBUG(SSSDBG_MINOR_FAILURE, ++ DEBUG(SSSDBG_OP_FAILURE, + "Could not delete cache entry [%s]\n", + ldb_dn_canonical_string(tmp_ctx, + update_dn)); +diff --git a/src/db/sysdb_ipnetworks.c b/src/db/sysdb_ipnetworks.c +index 326f984b7..9da4d9b23 100644 +--- a/src/db/sysdb_ipnetworks.c ++++ b/src/db/sysdb_ipnetworks.c +@@ -261,7 +261,7 @@ sysdb_store_ipnetwork(struct sss_domain_info *domain, + + ret = sysdb_delete_entry(sysdb, res->msgs[0]->dn, true); + if (ret != EOK) { +- DEBUG(SSSDBG_MINOR_FAILURE, ++ DEBUG(SSSDBG_OP_FAILURE, + "Could not delete cache entry [%s]\n", + ldb_dn_canonical_string(tmp_ctx, + res->msgs[0]->dn)); +@@ -296,7 +296,7 @@ sysdb_store_ipnetwork(struct sss_domain_info *domain, + + ret = sysdb_delete_entry(sysdb, res->msgs[i]->dn, true); + if (ret != EOK) { +- DEBUG(SSSDBG_MINOR_FAILURE, ++ DEBUG(SSSDBG_OP_FAILURE, + "Could not delete corrupt cache entry [%s]\n", + ldb_dn_canonical_string(tmp_ctx, + res->msgs[i]->dn)); +@@ -315,7 +315,7 @@ sysdb_store_ipnetwork(struct sss_domain_info *domain, + /* Delete the entry from the previous pass */ + ret = sysdb_delete_entry(sysdb, update_dn, true); + if (ret != EOK) { +- DEBUG(SSSDBG_MINOR_FAILURE, ++ DEBUG(SSSDBG_OP_FAILURE, + "Could not delete cache entry [%s]\n", + ldb_dn_canonical_string(tmp_ctx, + update_dn)); +diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c +index 3412b9cd1..585708abe 100644 +--- a/src/db/sysdb_ops.c ++++ b/src/db/sysdb_ops.c +@@ -157,7 +157,7 @@ static int sysdb_delete_cache_entry(struct ldb_context *ldb, + /* fall through */ + SSS_ATTRIBUTE_FALLTHROUGH; + default: +- DEBUG(SSSDBG_CRIT_FAILURE, "LDB Error: %s(%d)\nError Message: [%s]\n", ++ DEBUG(SSSDBG_CRIT_FAILURE, "LDB Error: %s (%d); error message: [%s]\n", + ldb_strerror(ret), ret, ldb_errstring(ldb)); + return sysdb_error_to_errno(ret); + } +@@ -3420,7 +3420,7 @@ int sysdb_search_custom(TALLOC_CTX *mem_ctx, + goto done; + } + if (!ldb_dn_validate(basedn)) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Failed to create DN.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "Syntactically invalid subtree DN.\n"); + ret = EINVAL; + goto done; + } +@@ -3463,7 +3463,7 @@ int sysdb_search_custom_by_name(TALLOC_CTX *mem_ctx, + goto done; + } + if (!ldb_dn_validate(basedn)) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Failed to create DN.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "Syntactically invalid DN.\n"); + ret = EINVAL; + goto done; + } +@@ -3545,7 +3545,7 @@ errno_t sysdb_search_by_orig_dn(TALLOC_CTX *mem_ctx, + default: + DEBUG(SSSDBG_CRIT_FAILURE, + "Trying to perform a search by orig_dn using a " +- "non-supported type\n"); ++ "non-supported type %d\n", type); + ret = EINVAL; + goto done; + } +@@ -3690,8 +3690,9 @@ int sysdb_delete_custom(struct sss_domain_info *domain, + break; + + default: +- DEBUG(SSSDBG_CRIT_FAILURE, "LDB Error: %s(%d)\nError Message: [%s]\n", +- ldb_strerror(ret), ret, ldb_errstring(domain->sysdb->ldb)); ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "ldb_delete failed: %s (%d); error Message: [%s]\n", ++ ldb_strerror(ret), ret, ldb_errstring(domain->sysdb->ldb)); + ret = sysdb_error_to_errno(ret); + break; + } +@@ -4927,9 +4928,15 @@ static errno_t sysdb_update_members_ex(struct sss_domain_info *domain, + ret = sysdb_add_group_member(domain, add_groups[i], + member, type, is_dn); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, +- "Could not add member [%s] to group [%s]. " +- "Skipping.\n", member, add_groups[i]); ++ if (ret != EEXIST) { ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Could not add member [%s] to group [%s]. " ++ "Skipping.\n", member, add_groups[i]); ++ } else { ++ DEBUG(SSSDBG_FUNC_DATA, ++ "Group [%s] already has member [%s]. Skipping.\n", ++ add_groups[i], member); ++ } + /* Continue on, we should try to finish the rest */ + } + } +@@ -4941,9 +4948,15 @@ static errno_t sysdb_update_members_ex(struct sss_domain_info *domain, + ret = sysdb_remove_group_member(domain, del_groups[i], + member, type, is_dn); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, +- "Could not remove member [%s] from group [%s]. " +- "Skipping\n", member, del_groups[i]); ++ if (ret != ENOENT) { ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Could not remove member [%s] from group [%s]. " ++ "Skipping\n", member, del_groups[i]); ++ } else { ++ DEBUG(SSSDBG_FUNC_DATA, ++ "No member [%s] in group [%s]. " ++ "Skipping\n", member, del_groups[i]); ++ } + /* Continue on, we should try to finish the rest */ + } + } +diff --git a/src/db/sysdb_search.c b/src/db/sysdb_search.c +index 4ff65c1ae..0cd8321cb 100644 +--- a/src/db/sysdb_search.c ++++ b/src/db/sysdb_search.c +@@ -2393,7 +2393,7 @@ errno_t sysdb_get_direct_parents(TALLOC_CTX *mem_ctx, + } else if (mtype == SYSDB_MEMBER_GROUP) { + dn = sysdb_group_strdn(tmp_ctx, dom->name, name); + } else { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unknown member type\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unknown member type %d\n", mtype); + ret = EINVAL; + goto done; + } +@@ -2453,13 +2453,14 @@ errno_t sysdb_get_direct_parents(TALLOC_CTX *mem_ctx, + tmp_str = ldb_msg_find_attr_as_string(direct_sysdb_groups[i], + SYSDB_NAME, NULL); + if (!tmp_str) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "A group with no name?\n"); + /* This should never happen, but if it does, just continue */ + continue; + } + + direct_parents[pi] = talloc_strdup(direct_parents, tmp_str); + if (!direct_parents[pi]) { +- DEBUG(SSSDBG_CRIT_FAILURE, "A group with no name?\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup() failed\n"); + ret = EIO; + goto done; + } +@@ -2522,8 +2523,13 @@ errno_t sysdb_get_real_name(TALLOC_CTX *mem_ctx, + } + if (ret != EOK) { + /* User cannot be found in cache */ +- DEBUG(SSSDBG_OP_FAILURE, "Cannot find user [%s] in cache\n", +- name_or_upn_or_sid); ++ if (ret != ENOENT) { ++ DEBUG(SSSDBG_OP_FAILURE, "Failed to find user [%s] in cache: %d\n", ++ name_or_upn_or_sid, ret); ++ } else { ++ DEBUG(SSSDBG_TRACE_FUNC, "User [%s] is missing in cache\n", ++ name_or_upn_or_sid); ++ } + goto done; + } + } else if (res->count == 1) { +@@ -2537,7 +2543,8 @@ errno_t sysdb_get_real_name(TALLOC_CTX *mem_ctx, + + cname = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL); + if (!cname) { +- DEBUG(SSSDBG_CRIT_FAILURE, "A user with no name?\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "User '%s' without a name?\n", name_or_upn_or_sid); + ret = ENOENT; + goto done; + } +diff --git a/src/db/sysdb_selinux.c b/src/db/sysdb_selinux.c +index 88ac88786..535411950 100644 +--- a/src/db/sysdb_selinux.c ++++ b/src/db/sysdb_selinux.c +@@ -234,7 +234,7 @@ errno_t sysdb_delete_usermaps(struct sss_domain_info *domain) + ret = sysdb_delete_recursive(sysdb, dn, true); + talloc_free(dn); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_delete_recursive failed.\n"); ++ DEBUG(SSSDBG_OP_FAILURE, "sysdb_delete_recursive failed.\n"); + return ret; + } + +diff --git a/src/db/sysdb_services.c b/src/db/sysdb_services.c +index 8118fef00..ac17f4704 100644 +--- a/src/db/sysdb_services.c ++++ b/src/db/sysdb_services.c +@@ -252,7 +252,7 @@ sysdb_store_service(struct sss_domain_info *domain, + + ret = sysdb_delete_entry(sysdb, res->msgs[0]->dn, true); + if (ret != EOK) { +- DEBUG(SSSDBG_MINOR_FAILURE, ++ DEBUG(SSSDBG_OP_FAILURE, + "Could not delete cache entry [%s]\n", + ldb_dn_canonical_string(tmp_ctx, + res->msgs[0]->dn)); +@@ -290,7 +290,7 @@ sysdb_store_service(struct sss_domain_info *domain, + + ret = sysdb_delete_entry(sysdb, res->msgs[i]->dn, true); + if (ret != EOK) { +- DEBUG(SSSDBG_MINOR_FAILURE, ++ DEBUG(SSSDBG_OP_FAILURE, + "Could not delete corrupt cache entry [%s]\n", + ldb_dn_canonical_string(tmp_ctx, + res->msgs[i]->dn)); +@@ -310,7 +310,7 @@ sysdb_store_service(struct sss_domain_info *domain, + /* Delete the entry from the previous pass */ + ret = sysdb_delete_entry(sysdb, update_dn, true); + if (ret != EOK) { +- DEBUG(SSSDBG_MINOR_FAILURE, ++ DEBUG(SSSDBG_OP_FAILURE, + "Could not delete cache entry [%s]\n", + ldb_dn_canonical_string(tmp_ctx, + update_dn)); +diff --git a/src/db/sysdb_sudo.c b/src/db/sysdb_sudo.c +index 03eec9c70..1626b612d 100644 +--- a/src/db/sysdb_sudo.c ++++ b/src/db/sysdb_sudo.c +@@ -480,7 +480,8 @@ sysdb_get_sudo_user_info(TALLOC_CTX *mem_ctx, + sss_get_cased_name(sysdb_groupnames, groupname, + domain->case_sensitive); + if (sysdb_groupnames[num_groups] == NULL) { +- DEBUG(SSSDBG_MINOR_FAILURE, "Cannot strdup %s\n", groupname); ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "sss_get_cased_name() failed for '%s'\n", groupname); + continue; + } + num_groups++; +diff --git a/src/db/sysdb_upgrade.c b/src/db/sysdb_upgrade.c +index 03a0e6173..99213260c 100644 +--- a/src/db/sysdb_upgrade.c ++++ b/src/db/sysdb_upgrade.c +@@ -2455,7 +2455,7 @@ int sysdb_upgrade_19(struct sysdb_ctx *sysdb, const char **ver) + + ret = add_object_category(sysdb->ldb, ctx); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "add_object_category failed.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "add_object_category failed: %d\n", ret); + goto done; + } + +diff --git a/src/db/sysdb_views.c b/src/db/sysdb_views.c +index 00da74047..269dab70f 100644 +--- a/src/db/sysdb_views.c ++++ b/src/db/sysdb_views.c +@@ -556,12 +556,12 @@ errno_t sysdb_store_override(struct sss_domain_info *domain, + if (ret == ENOENT) { + DEBUG(SSSDBG_CRIT_FAILURE, "Object to override does not exists.\n"); + } else { +- DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_entry failed.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_search_entry failed.\n"); + } + goto done; + } + if (count != 1) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Base searched returned more than one object.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "Base search returned more than one object.\n"); + ret = EINVAL; + goto done; + } +@@ -660,7 +660,7 @@ errno_t sysdb_store_override(struct sss_domain_info *domain, + SYSDB_OVERRIDE_GROUP_CLASS); + break; + default: +- DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected object type.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected object type %d.\n", type); + ret = EINVAL; + goto done; + } +diff --git a/src/lib/certmap/sss_certmap_krb5_match.c b/src/lib/certmap/sss_certmap_krb5_match.c +index 640930747..ab566ac99 100644 +--- a/src/lib/certmap/sss_certmap_krb5_match.c ++++ b/src/lib/certmap/sss_certmap_krb5_match.c +@@ -220,7 +220,6 @@ static int parse_krb5_get_eku_value(TALLOC_CTX *mem_ctx, + + for (c = 0; eku_list[c] != NULL; c++) { + for (k = 0; sss_ext_key_usage[k].name != NULL; k++) { +-CM_DEBUG(ctx, "[%s][%s].", eku_list[c], sss_ext_key_usage[k].name); + if (strcasecmp(eku_list[c], sss_ext_key_usage[k].name) == 0) { + comp->eku_oid_list[e] = talloc_strdup(comp->eku_oid_list, + sss_ext_key_usage[k].oid); +diff --git a/src/man/include/debug_levels.xml b/src/man/include/debug_levels.xml +index b5e13ba3e..0d9cc17be 100644 +--- a/src/man/include/debug_levels.xml ++++ b/src/man/include/debug_levels.xml +@@ -100,6 +100,7 @@ + introduced in 1.7.0. + + +- Default: 0 ++ Default: 0x0070 (i.e. fatal, critical and serious ++ failures; corresponds to setting 2 in decimal notation) + + +diff --git a/src/man/include/debug_levels_tools.xml b/src/man/include/debug_levels_tools.xml +index b592d50fc..46a3c7d29 100644 +--- a/src/man/include/debug_levels_tools.xml ++++ b/src/man/include/debug_levels_tools.xml +@@ -81,6 +81,7 @@ + introduced in 1.7.0. + + +- Default: 0 ++ Default: 0x0070 (i.e. fatal, critical and serious ++ failures; corresponds to setting 2 in decimal notation) + + +diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c +index d9da05a51..9c2381c81 100644 +--- a/src/monitor/monitor.c ++++ b/src/monitor/monitor.c +@@ -1435,7 +1435,7 @@ static void monitor_quit(struct mt_ctx *mt_ctx, int ret) + DEBUG(SSSDBG_CRIT_FAILURE, + "Child [%s] terminated with a signal\n", svc->name); + } else { +- DEBUG(SSSDBG_FATAL_FAILURE, ++ DEBUG(SSSDBG_CRIT_FAILURE, + "Child [%s] did not exit cleanly\n", svc->name); + /* Forcibly kill this child */ + kill(-svc->pid, SIGKILL); +@@ -2059,7 +2059,7 @@ static void monitor_sbus_connected(struct tevent_req *req) + + ret = sbus_connection_add_path_map(ctx->sbus_conn, paths); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add paths [%d]: %s\n", ++ DEBUG(SSSDBG_FATAL_FAILURE, "Unable to add paths [%d]: %s\n", + ret, sss_strerror(ret)); + goto done; + } +@@ -2271,7 +2271,7 @@ static void mt_svc_restart(struct tevent_context *ev, + add_new_provider(svc->mt_ctx, svc->name, svc->restarts + 1); + } else { + /* Invalid type? */ +- DEBUG(SSSDBG_CRIT_FAILURE, ++ DEBUG(SSSDBG_FATAL_FAILURE, + "BUG: Invalid child process type [%d]\n", svc->type); + } + +@@ -2580,14 +2580,14 @@ int main(int argc, const char *argv[]) + switch (ret) { + case EPERM: + case EACCES: +- DEBUG(SSSDBG_CRIT_FAILURE, ++ DEBUG(SSSDBG_FATAL_FAILURE, + CONF_FILE_PERM_ERROR_MSG, config_file); +- sss_log(SSS_LOG_ALERT, CONF_FILE_PERM_ERROR_MSG, config_file); ++ sss_log(SSS_LOG_CRIT, CONF_FILE_PERM_ERROR_MSG, config_file); + break; + default: +- DEBUG(SSSDBG_CRIT_FAILURE, ++ DEBUG(SSSDBG_FATAL_FAILURE, + "SSSD couldn't load the configuration database.\n"); +- sss_log(SSS_LOG_ALERT, ++ sss_log(SSS_LOG_CRIT, + "SSSD couldn't load the configuration database [%d]: %s.\n", + ret, strerror(ret)); + break; +diff --git a/src/p11_child/p11_child_common.c b/src/p11_child/p11_child_common.c +index f17de1a9e..704ced4b6 100644 +--- a/src/p11_child/p11_child_common.c ++++ b/src/p11_child/p11_child_common.c +@@ -125,7 +125,7 @@ static errno_t p11c_recv_data(TALLOC_CTX *mem_ctx, int fd, char **pin) + + str = talloc_strndup(mem_ctx, (char *) buf, len); + if (str == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strndup failed.\n"); + return ENOMEM; + } + +diff --git a/src/p11_child/p11_child_common_utils.c b/src/p11_child/p11_child_common_utils.c +index 50cfebb4c..c5f324625 100644 +--- a/src/p11_child/p11_child_common_utils.c ++++ b/src/p11_child/p11_child_common_utils.c +@@ -107,6 +107,9 @@ errno_t parse_cert_verify_opts(TALLOC_CTX *mem_ctx, const char *verify_opts, + "Found 'no_verification' option, " + "disabling verification completely. " + "This should not be used in production.\n"); ++ sss_log(SSS_LOG_CRIT, ++ "Smart card certificate verification disabled completely. " ++ "This should not be used in production."); + cert_verify_opts->do_verification = false; + } else if (strncasecmp(opts[c], OCSP_DEFAUL_RESPONDER, + OCSP_DEFAUL_RESPONDER_LEN) == 0) { +diff --git a/src/p11_child/p11_child_openssl.c b/src/p11_child/p11_child_openssl.c +index d81a1a9ea..879b05b65 100644 +--- a/src/p11_child/p11_child_openssl.c ++++ b/src/p11_child/p11_child_openssl.c +@@ -226,7 +226,7 @@ static char *get_issuer_subject_str(TALLOC_CTX *mem_ctx, X509 *cert) + + bio_mem = BIO_new(BIO_s_mem()); + if (bio_mem == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, "BIO_new failed.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "BIO_new failed.\n"); + return NULL; + } + +@@ -591,7 +591,7 @@ errno_t init_p11_ctx(TALLOC_CTX *mem_ctx, const char *ca_db, + ret = SSL_library_init(); + #endif + if (ret != 1) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Failed to initialize OpenSSL.\n"); ++ DEBUG(SSSDBG_FATAL_FAILURE, "Failed to initialize OpenSSL.\n"); + return EIO; + } + +diff --git a/src/providers/ad/ad_cldap_ping.c b/src/providers/ad/ad_cldap_ping.c +index ab234f4d7..7722af98a 100644 +--- a/src/providers/ad/ad_cldap_ping.c ++++ b/src/providers/ad/ad_cldap_ping.c +@@ -467,7 +467,7 @@ ad_cldap_ping_domain_send(TALLOC_CTX *mem_ctx, + domains[0] = discovery_domain; + domains[1] = NULL; + if (domains[0] == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "Bad argument (discovery_domain)"); + ret = ENOMEM; + goto done; + } +diff --git a/src/providers/ad/ad_common.c b/src/providers/ad/ad_common.c +index 624313942..eaa920ca0 100644 +--- a/src/providers/ad/ad_common.c ++++ b/src/providers/ad/ad_common.c +@@ -1072,15 +1072,14 @@ ad_resolve_callback(void *private_data, struct fo_server *server) + } + + if (!service->gc->uri) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Failed to append to URI\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "NULL GC URI\n"); + ret = ENOMEM; + goto done; + } + DEBUG(SSSDBG_CONF_SETTINGS, "Constructed GC uri '%s'\n", service->gc->uri); + + if (service->gc->sockaddr == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, +- "resolv_get_sockaddr_address failed.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "NULL GC sockaddr\n"); + ret = EIO; + goto done; + } +@@ -1100,7 +1099,7 @@ ad_resolve_callback(void *private_data, struct fo_server *server) + done: + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, +- "Error: [%s]\n", strerror(ret)); ++ "Error: %d [%s]\n", ret, strerror(ret)); + } + talloc_free(tmp_ctx); + return; +diff --git a/src/providers/ad/ad_dyndns.c b/src/providers/ad/ad_dyndns.c +index 71ef16c0b..19fc8acef 100644 +--- a/src/providers/ad/ad_dyndns.c ++++ b/src/providers/ad/ad_dyndns.c +@@ -63,7 +63,7 @@ errno_t ad_dyndns_init(struct be_ctx *be_ctx, + */ + ret = ad_get_dyndns_options(be_ctx, ad_opts); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Could not set AD options\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "Could not get AD dyndns options\n"); + return ret; + } + +@@ -209,8 +209,8 @@ static void ad_dyndns_update_connect_done(struct tevent_req *subreq) + + ret = ldap_url_parse(ctx->service->sdap->uri, &lud); + if (ret != LDAP_SUCCESS) { +- DEBUG(SSSDBG_CRIT_FAILURE, +- "Failed to parse ldap URI (%s)!\n", ctx->service->sdap->uri); ++ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to parse ldap URI '%s': %d\n", ++ ctx->service->sdap->uri, ret); + ret = EINVAL; + goto done; + } +diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c +index 0eb5416ac..b15e0f345 100644 +--- a/src/providers/ad/ad_gpo.c ++++ b/src/providers/ad/ad_gpo.c +@@ -671,7 +671,9 @@ ad_gpo_ace_includes_client_sid(const char *user_sid, + + err = sss_idmap_sid_to_smb_sid(idmap_ctx, user_sid, &user_dom_sid); + if (err != IDMAP_SUCCESS) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Failed to initialize idmap context.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "sss_idmap_sid_to_smb_sid() failed for user_sid '%s': %d\n", ++ user_sid, err); + return EFAULT; + } + +@@ -684,7 +686,9 @@ ad_gpo_ace_includes_client_sid(const char *user_sid, + + err = sss_idmap_sid_to_smb_sid(idmap_ctx, host_sid, &host_dom_sid); + if (err != IDMAP_SUCCESS) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Failed to initialize idmap context.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "sss_idmap_sid_to_smb_sid() failed for host_sid '%s': %d\n", ++ host_sid, err); + return EFAULT; + } + +@@ -698,7 +702,9 @@ ad_gpo_ace_includes_client_sid(const char *user_sid, + for (i = 0; i < group_size; i++) { + err = sss_idmap_sid_to_smb_sid(idmap_ctx, group_sids[i], &group_dom_sid); + if (err != IDMAP_SUCCESS) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Failed to initialize idmap context.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "sss_idmap_sid_to_smb_sid() failed for group_sid '%s': %d\n", ++ group_sids[i], err); + return EFAULT; + } + included = ad_gpo_dom_sid_equal(&ace_dom_sid, group_dom_sid); +@@ -4777,14 +4783,14 @@ gpo_fork_child(struct tevent_req *req) + if (ret == -1) { + ret = errno; + DEBUG(SSSDBG_CRIT_FAILURE, +- "pipe failed [%d][%s].\n", errno, strerror(errno)); ++ "pipe (from) failed [%d][%s].\n", errno, strerror(errno)); + goto fail; + } + ret = pipe(pipefd_to_child); + if (ret == -1) { + ret = errno; + DEBUG(SSSDBG_CRIT_FAILURE, +- "pipe failed [%d][%s].\n", errno, strerror(errno)); ++ "pipe (to) failed [%d][%s].\n", errno, strerror(errno)); + goto fail; + } + +diff --git a/src/providers/ad/ad_machine_pw_renewal.c b/src/providers/ad/ad_machine_pw_renewal.c +index ce9bbe6f3..6e7137a86 100644 +--- a/src/providers/ad/ad_machine_pw_renewal.c ++++ b/src/providers/ad/ad_machine_pw_renewal.c +@@ -171,14 +171,14 @@ ad_machine_account_password_renewal_send(TALLOC_CTX *mem_ctx, + if (ret == -1) { + ret = errno; + DEBUG(SSSDBG_CRIT_FAILURE, +- "pipe failed [%d][%s].\n", ret, strerror(ret)); ++ "pipe (from) failed [%d][%s].\n", ret, strerror(ret)); + goto done; + } + ret = pipe(pipefd_to_child); + if (ret == -1) { + ret = errno; + DEBUG(SSSDBG_CRIT_FAILURE, +- "pipe failed [%d][%s].\n", ret, strerror(ret)); ++ "pipe (to) failed [%d][%s].\n", ret, strerror(ret)); + goto done; + } + +@@ -354,7 +354,8 @@ errno_t ad_machine_account_password_renewal_init(struct be_ctx *be_ctx, + } + + if (opt_list_size != 2) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Wrong number of renewal options.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "Wrong number of renewal options %d\n", ++ opt_list_size); + ret = EINVAL; + goto done; + } +diff --git a/src/providers/ad/ad_pac.c b/src/providers/ad/ad_pac.c +index 80424b44e..aff47304e 100644 +--- a/src/providers/ad/ad_pac.c ++++ b/src/providers/ad/ad_pac.c +@@ -120,7 +120,11 @@ errno_t check_if_pac_is_available(TALLOC_CTX *mem_ctx, + + ret = find_user_entry(mem_ctx, dom, ar, &msg); + if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, "find_user_entry failed.\n"); ++ if (ret == ENOENT) { ++ DEBUG(SSSDBG_FUNC_DATA, "find_user_entry didn't find user entry.\n"); ++ } else { ++ DEBUG(SSSDBG_OP_FAILURE, "find_user_entry failed.\n"); ++ } + return ret; + } + +diff --git a/src/providers/ad/ad_subdomains.c b/src/providers/ad/ad_subdomains.c +index 4c457b7e5..f5b0be6c2 100644 +--- a/src/providers/ad/ad_subdomains.c ++++ b/src/providers/ad/ad_subdomains.c +@@ -299,7 +299,7 @@ ad_subdom_ad_ctx_new(struct be_ctx *be_ctx, + + subdom_conf_path = subdomain_create_conf_path(id_ctx, subdom); + if (subdom_conf_path == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "subdom_conf_path failed\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "subdomain_create_conf_path failed\n"); + return ENOMEM; + } + +diff --git a/src/providers/be_dyndns.c b/src/providers/be_dyndns.c +index 2de3b11bb..1a304db37 100644 +--- a/src/providers/be_dyndns.c ++++ b/src/providers/be_dyndns.c +@@ -1111,7 +1111,8 @@ be_nsupdate_args(TALLOC_CTX *mem_ctx, + argc++; + break; + default: +- DEBUG(SSSDBG_CRIT_FAILURE, "Unknown nsupdate auth type\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Unknown nsupdate auth type %d\n", auth_type); + goto fail; + } + +diff --git a/src/providers/be_ptask.c b/src/providers/be_ptask.c +index fb80909a0..fab9e21b8 100644 +--- a/src/providers/be_ptask.c ++++ b/src/providers/be_ptask.c +@@ -251,7 +251,7 @@ static void be_ptask_schedule(struct be_ptask *task, + task->timer = tevent_add_timer(task->ev, task, tv, be_ptask_execute, task); + if (task->timer == NULL) { + /* nothing we can do about it */ +- DEBUG(SSSDBG_CRIT_FAILURE, "FATAL: Unable to schedule task [%s]\n", ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to schedule task [%s]\n", + task->name); + be_ptask_disable(task); + } +diff --git a/src/providers/be_refresh.c b/src/providers/be_refresh.c +index 01cbf03e2..fdddf8bca 100644 +--- a/src/providers/be_refresh.c ++++ b/src/providers/be_refresh.c +@@ -125,7 +125,8 @@ static errno_t be_refresh_get_values(TALLOC_CTX *mem_ctx, + base_dn = sysdb_netgroup_base_dn(mem_ctx, domain); + break; + default: +- DEBUG(SSSDBG_CRIT_FAILURE, "Uknown or unsupported refresh type\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Uknown or unsupported refresh type %d\n", type); + return ERR_INTERNAL; + break; + } +diff --git a/src/providers/data_provider/dp.c b/src/providers/data_provider/dp.c +index 0858c43d2..90324d74d 100644 +--- a/src/providers/data_provider/dp.c ++++ b/src/providers/data_provider/dp.c +@@ -109,7 +109,7 @@ dp_init_interface(struct data_provider *provider) + + ret = sbus_connection_add_path_map(provider->sbus_conn, paths); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add paths [%d]: %s\n", ++ DEBUG(SSSDBG_FATAL_FAILURE, "Unable to add paths [%d]: %s\n", + ret, sss_strerror(ret)); + } + +@@ -196,7 +196,7 @@ dp_init_send(TALLOC_CTX *mem_ctx, + (sbus_server_on_connection_cb)dp_client_init, + (sbus_server_on_connection_data)state->provider); + if (subreq == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create subrequest!\n"); ++ DEBUG(SSSDBG_FATAL_FAILURE, "Unable to create subrequest!\n"); + ret = ENOMEM; + goto done; + } +diff --git a/src/providers/data_provider/dp_target_sudo.c b/src/providers/data_provider/dp_target_sudo.c +index db14039c4..59e2358cc 100644 +--- a/src/providers/data_provider/dp_target_sudo.c ++++ b/src/providers/data_provider/dp_target_sudo.c +@@ -42,13 +42,13 @@ static errno_t dp_sudo_parse_message(TALLOC_CTX *mem_ctx, + + ret = sbus_iterator_read_u(read_iter, &dp_flags); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Failed, to parse the message!\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to parse the message (flags)!\n"); + return ret; + } + + ret = sbus_iterator_read_u(read_iter, &sudo_type); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Failed, to parse the message!\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to parse the message (type)!\n"); + return ret; + } + +@@ -66,13 +66,15 @@ static errno_t dp_sudo_parse_message(TALLOC_CTX *mem_ctx, + /* read rules_num */ + ret = sbus_iterator_read_u(read_iter, &num_rules); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Failed, to parse the message!\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Failed to parse the message (num rules)!\n"); + return ret; + } + + ret = sbus_iterator_read_as(mem_ctx, read_iter, &rules); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Failed, to parse the message!\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Failed to parse the message (rules)!\n"); + return ret; + } + break; +diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c +index 10421c6b4..f059a3f96 100644 +--- a/src/providers/data_provider_be.c ++++ b/src/providers/data_provider_be.c +@@ -407,7 +407,7 @@ static void check_if_online(struct be_ctx *be_ctx, int delay) + check_if_online_delayed, be_ctx); + + if (time_event == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, ++ DEBUG(SSSDBG_CRIT_FAILURE, + "Scheduling check_if_online_delayed failed.\n"); + goto failed; + } +@@ -420,7 +420,6 @@ static void check_if_online(struct be_ctx *be_ctx, int delay) + + failed: + be_ctx->check_online_ref_count--; +- DEBUG(SSSDBG_CRIT_FAILURE, "Failed to run a check_online test.\n"); + + if (be_ctx->check_online_ref_count == 0) { + reset_fo(be_ctx); +@@ -629,7 +628,7 @@ static void dp_initialized(struct tevent_req *req) + + ret = be_register_monitor_iface(be_ctx->mon_conn, be_ctx); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to register monitor interface " ++ DEBUG(SSSDBG_FATAL_FAILURE, "Unable to register monitor interface " + "[%d]: %s\n", ret, sss_strerror(ret)); + goto done; + } +diff --git a/src/providers/data_provider_fo.c b/src/providers/data_provider_fo.c +index 8dc09f5b2..0dfbb04b0 100644 +--- a/src/providers/data_provider_fo.c ++++ b/src/providers/data_provider_fo.c +@@ -651,7 +651,7 @@ errno_t be_resolve_server_process(struct tevent_req *subreq, + srvaddr = fo_get_server_hostent(state->srv); + if (!srvaddr) { + DEBUG(SSSDBG_CRIT_FAILURE, +- "FATAL: No hostent available for server (%s)\n", ++ "No hostent available for server (%s)\n", + fo_get_server_str_name(state->srv)); + return EFAULT; + } +diff --git a/src/providers/data_provider_opts.c b/src/providers/data_provider_opts.c +index 9db43fc40..bb543ae4f 100644 +--- a/src/providers/data_provider_opts.c ++++ b/src/providers/data_provider_opts.c +@@ -233,7 +233,7 @@ static int dp_copy_options_ex(TALLOC_CTX *memctx, + } + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, +- "Failed to retrieve value for option (%s)\n", ++ "Failed to copy value for option (%s)\n", + opts[i].opt_name); + goto done; + } +@@ -249,7 +249,7 @@ static int dp_copy_options_ex(TALLOC_CTX *memctx, + } + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, +- "Failed to retrieve value for option (%s)\n", ++ "Failed to copy value for option (%s)\n", + opts[i].opt_name); + goto done; + } +@@ -265,7 +265,7 @@ static int dp_copy_options_ex(TALLOC_CTX *memctx, + } + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, +- "Failed to retrieve value for option (%s)\n", ++ "Failed to copy value for option (%s)\n", + opts[i].opt_name); + goto done; + } +diff --git a/src/providers/data_provider_req.h b/src/providers/data_provider_req.h +index f2e05797f..75f7f9713 100644 +--- a/src/providers/data_provider_req.h ++++ b/src/providers/data_provider_req.h +@@ -39,6 +39,7 @@ + #define BE_REQ_USER_AND_GROUP 0x0012 + #define BE_REQ_BY_UUID 0x0013 + #define BE_REQ_BY_CERT 0x0014 ++#define BE_REQ__LAST BE_REQ_BY_CERT /* must be equal to max REQ number */ + #define BE_REQ_TYPE_MASK 0x00FF + + /** +diff --git a/src/providers/files/files_ops.c b/src/providers/files/files_ops.c +index 59fc20692..54d2b4164 100644 +--- a/src/providers/files/files_ops.c ++++ b/src/providers/files/files_ops.c +@@ -395,7 +395,7 @@ static errno_t refresh_override_attrs(struct files_id_ctx *id_ctx, + override_attrs, &count, &msgs); + if (ret != EOK) { + if (ret == ENOENT) { +- DEBUG(SSSDBG_OP_FAILURE, "No overrides, nothing to do.\n"); ++ DEBUG(SSSDBG_TRACE_FUNC, "No overrides, nothing to do.\n"); + ret = EOK; + } else { + DEBUG(SSSDBG_OP_FAILURE, "sysdb_search_entry failed.\n"); +diff --git a/src/providers/ipa/ipa_access.c b/src/providers/ipa/ipa_access.c +index 375b6f885..4a6727c97 100644 +--- a/src/providers/ipa/ipa_access.c ++++ b/src/providers/ipa/ipa_access.c +@@ -671,7 +671,7 @@ static void ipa_pam_access_handler_done(struct tevent_req *subreq) + talloc_free(subreq); + + if (ret == ENOENT) { +- DEBUG(SSSDBG_CRIT_FAILURE, "No HBAC rules find, denying access\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "No HBAC rules found, denying access\n"); + state->pd->pam_status = PAM_PERM_DENIED; + goto done; + } else if (ret != EOK) { +diff --git a/src/providers/ipa/ipa_common.c b/src/providers/ipa/ipa_common.c +index 1211ba4c9..8cadb9249 100644 +--- a/src/providers/ipa/ipa_common.c ++++ b/src/providers/ipa/ipa_common.c +@@ -781,8 +781,7 @@ int ipa_get_auth_options(struct ipa_options *ipa_opts, + dp_opt_get_string(ipa_opts->auth, + KRB5_REALM)); + if (value == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Cannot set %s!\n", +- ipa_opts->auth[KRB5_FAST_PRINCIPAL].opt_name); ++ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf() failed\n"); + ret = ENOMEM; + goto done; + } +@@ -851,7 +850,7 @@ static void ipa_resolve_callback(void *private_data, struct fo_server *server) + srvaddr = fo_get_server_hostent(server); + if (!srvaddr) { + DEBUG(SSSDBG_CRIT_FAILURE, +- "FATAL: No hostent available for server (%s)\n", ++ "No hostent available for server (%s)\n", + fo_get_server_str_name(server)); + talloc_free(tmp_ctx); + return; +diff --git a/src/providers/ipa/ipa_hbac_common.c b/src/providers/ipa/ipa_hbac_common.c +index 31e53d24d..1fee41a36 100644 +--- a/src/providers/ipa/ipa_hbac_common.c ++++ b/src/providers/ipa/ipa_hbac_common.c +@@ -423,7 +423,7 @@ hbac_eval_user_element(TALLOC_CTX *mem_ctx, + ret = sysdb_initgroups(tmp_ctx, domain, username, &res); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, +- "sysdb_asq_search failed [%d]: %s\n", ret, sss_strerror(ret)); ++ "sysdb_initgroups() failed [%d]: %s\n", ret, sss_strerror(ret)); + goto done; + } + +diff --git a/src/providers/ipa/ipa_hbac_services.c b/src/providers/ipa/ipa_hbac_services.c +index 79088ff66..387e915cd 100644 +--- a/src/providers/ipa/ipa_hbac_services.c ++++ b/src/providers/ipa/ipa_hbac_services.c +@@ -487,7 +487,7 @@ hbac_service_attrs_to_rule(TALLOC_CTX *mem_ctx, + /* Original DN matched a single service. Get the service name */ + name = ldb_msg_find_attr_as_string(msgs[0], IPA_CN, NULL); + if (name == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Attribute is missing!\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "Attribute IPA_CN is missing!\n"); + ret = EFAULT; + goto done; + } +@@ -523,7 +523,7 @@ hbac_service_attrs_to_rule(TALLOC_CTX *mem_ctx, + /* Original DN matched a single group. Get the groupname */ + name = ldb_msg_find_attr_as_string(msgs[0], IPA_CN, NULL); + if (name == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Attribute is missing!\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "Attribute IPA_CN is missing!\n"); + ret = EFAULT; + goto done; + } +diff --git a/src/providers/ipa/ipa_hbac_users.c b/src/providers/ipa/ipa_hbac_users.c +index 2801a3162..25850eac0 100644 +--- a/src/providers/ipa/ipa_hbac_users.c ++++ b/src/providers/ipa/ipa_hbac_users.c +@@ -124,7 +124,7 @@ get_ipa_groupname(TALLOC_CTX *mem_ctx, + if (strcasecmp("cn", account_comp_name) != 0) { + /* The third component name is not "cn" */ + DEBUG(SSSDBG_CRIT_FAILURE, +- "Expected cn in second component, got %s\n", account_comp_name); ++ "Expected cn in third component, got %s\n", account_comp_name); + ret = ERR_UNEXPECTED_ENTRY_TYPE; + goto done; + } +@@ -135,7 +135,7 @@ get_ipa_groupname(TALLOC_CTX *mem_ctx, + account_comp_val->length) != 0) { + /* The third component value is not "accounts" */ + DEBUG(SSSDBG_CRIT_FAILURE, +- "Expected cn accounts second component, got %s\n", ++ "Expected accounts third component, got %s\n", + (const char *) account_comp_val->data); + ret = ERR_UNEXPECTED_ENTRY_TYPE; + goto done; +diff --git a/src/providers/ipa/ipa_id.c b/src/providers/ipa/ipa_id.c +index 9253514a3..2cbe0c9c7 100644 +--- a/src/providers/ipa/ipa_id.c ++++ b/src/providers/ipa/ipa_id.c +@@ -266,7 +266,7 @@ ipa_initgr_get_overrides_send(TALLOC_CTX *memctx, + } + state->groups_id_attr = talloc_strdup(state, groups_id_attr); + if (state->groups_id_attr == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup failed.\n"); + ret = ENOMEM; + goto done; + } +diff --git a/src/providers/ipa/ipa_init.c b/src/providers/ipa/ipa_init.c +index a4d58e3bd..afdd6fdd0 100644 +--- a/src/providers/ipa/ipa_init.c ++++ b/src/providers/ipa/ipa_init.c +@@ -317,10 +317,10 @@ static errno_t ipa_init_client_mode(struct be_ctx *be_ctx, + ret = sysdb_get_view_name(ipa_id_ctx, be_ctx->domain->sysdb, + &ipa_id_ctx->view_name); + if (ret == ENOENT) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Cannot find view name in the cache. " ++ DEBUG(SSSDBG_MINOR_FAILURE, "Cannot find view name in the cache. " + "Will do online lookup later.\n"); + } else if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, "sysdb_get_view_name() failed [%d]: %s\n", ++ DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_get_view_name() failed [%d]: %s\n", + ret, sss_strerror(ret)); + return ret; + } +diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c +index c3e1acb48..fb93c6233 100644 +--- a/src/providers/ipa/ipa_s2n_exop.c ++++ b/src/providers/ipa/ipa_s2n_exop.c +@@ -2224,7 +2224,8 @@ static void ipa_s2n_get_user_done(struct tevent_req *subreq) + + break; + default: +- DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected request type.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Unexpected request type %d.\n", state->request_type); + ret = EINVAL; + goto done; + } +diff --git a/src/providers/ipa/ipa_selinux.c b/src/providers/ipa/ipa_selinux.c +index 5cb02de86..760349134 100644 +--- a/src/providers/ipa/ipa_selinux.c ++++ b/src/providers/ipa/ipa_selinux.c +@@ -681,7 +681,7 @@ static errno_t selinux_fork_child(struct selinux_child_state *state) + if (ret == -1) { + ret = errno; + DEBUG(SSSDBG_CRIT_FAILURE, +- "pipe failed [%d][%s].\n", errno, sss_strerror(errno)); ++ "pipe (from) failed [%d][%s].\n", errno, sss_strerror(errno)); + return ret; + } + +@@ -689,7 +689,7 @@ static errno_t selinux_fork_child(struct selinux_child_state *state) + if (ret == -1) { + ret = errno; + DEBUG(SSSDBG_CRIT_FAILURE, +- "pipe failed [%d][%s].\n", errno, sss_strerror(errno)); ++ "pipe (to) failed [%d][%s].\n", errno, sss_strerror(errno)); + return ret; + } + +diff --git a/src/providers/ipa/ipa_session.c b/src/providers/ipa/ipa_session.c +index 6672cb349..935393ccd 100644 +--- a/src/providers/ipa/ipa_session.c ++++ b/src/providers/ipa/ipa_session.c +@@ -570,7 +570,7 @@ ipa_pam_session_handler_done(struct tevent_req *subreq) + talloc_free(subreq); + + if (ret == ENOENT) { +- DEBUG(SSSDBG_IMPORTANT_INFO, "No Desktop Profile rules found\n"); ++ DEBUG(SSSDBG_FUNC_DATA, "No Desktop Profile rules found\n"); + if (!state->session_ctx->no_rules_found) { + state->session_ctx->no_rules_found = true; + state->session_ctx->last_request = time(NULL); +@@ -668,7 +668,7 @@ ipa_pam_session_handler_get_deskprofile_user_info(TALLOC_CTX *mem_ctx, + + if (res->count != 1) { + DEBUG(SSSDBG_CRIT_FAILURE, +- "sysdb_getpwnam() got more users than expected. " ++ "sysdb_getpwnam() returned unexpected amount of users. " + "Expected [%d], got [%d]\n", 1, res->count); + ret = EINVAL; + goto done; +diff --git a/src/providers/ipa/ipa_subdomains_ext_groups.c b/src/providers/ipa/ipa_subdomains_ext_groups.c +index c730c3317..790ae9d16 100644 +--- a/src/providers/ipa/ipa_subdomains_ext_groups.c ++++ b/src/providers/ipa/ipa_subdomains_ext_groups.c +@@ -840,7 +840,8 @@ static void ipa_add_ad_memberships_get_next(struct tevent_req *req) + } + + if (missing_groups) { +- DEBUG(SSSDBG_CRIT_FAILURE, "There are unresolved external group " ++ /* this might be HBAC or sudo rule */ ++ DEBUG(SSSDBG_FUNC_DATA, "There are unresolved external group " + "memberships even after all groups " + "have been looked up on the LDAP " + "server.\n"); +diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c +index 36f32fae8..46d496258 100644 +--- a/src/providers/ipa/ipa_subdomains_id.c ++++ b/src/providers/ipa/ipa_subdomains_id.c +@@ -506,7 +506,13 @@ struct tevent_req *ipa_get_subdom_acct_send(TALLOC_CTX *memctx, + break; + default: + ret = EINVAL; +- DEBUG(SSSDBG_OP_FAILURE, "Invalid sub-domain request type.\n"); ++ if (state->entry_type > BE_REQ__LAST) { ++ DEBUG(SSSDBG_OP_FAILURE, "Invalid sub-domain request type %d.\n", ++ state->entry_type); ++ } else { ++ DEBUG(SSSDBG_TRACE_FUNC, "Unhandled sub-domain request type %d.\n", ++ state->entry_type); ++ } + } + if (ret != EOK) goto fail; + +@@ -1027,6 +1033,9 @@ apply_subdomain_homedir(TALLOC_CTX *mem_ctx, struct sss_domain_info *dom, + const char *homedir = NULL; + struct ldb_message_element *msg_el = NULL; + size_t c; ++ const char *category = NULL; ++ size_t length = 0; ++ bool user_class = true; + + msg_el = ldb_msg_find_element(msg, SYSDB_OBJECTCATEGORY); + if (msg_el == NULL) { +@@ -1039,12 +1048,15 @@ apply_subdomain_homedir(TALLOC_CTX *mem_ctx, struct sss_domain_info *dom, + * case of a MPG group lookup if SYSDB_OBJECTCATEGORY is SYSDB_GROUP_CLASS. + */ + for (c = 0; c < msg_el->num_values; c++) { +- if (strncmp(SYSDB_USER_CLASS, (const char *)msg_el->values[c].data, +- msg_el->values[c].length) == 0 +- || (sss_domain_is_mpg(dom) +- && strncmp(SYSDB_GROUP_CLASS, +- (const char *)msg_el->values[c].data, +- msg_el->values[c].length) == 0)) { ++ category = (const char *)msg_el->values[c].data; ++ length = msg_el->values[c].length; ++ if (strncmp(SYSDB_USER_CLASS, category, length) == 0) { ++ user_class = true; ++ break; ++ } ++ if (sss_domain_is_mpg(dom) ++ && strncmp(SYSDB_GROUP_CLASS, category, length) == 0) { ++ user_class = false; + break; + } + } +@@ -1064,8 +1076,12 @@ apply_subdomain_homedir(TALLOC_CTX *mem_ctx, struct sss_domain_info *dom, + + uid = ldb_msg_find_attr_as_uint64(msg, SYSDB_UIDNUM, 0); + if (uid == 0) { +- DEBUG(SSSDBG_OP_FAILURE, "UID for user [%s] is not known.\n", +- fqname); ++ if (user_class) { ++ DEBUG(SSSDBG_OP_FAILURE, "UID for user [%s] is unknown\n", fqname); ++ } else { ++ DEBUG(SSSDBG_TRACE_INTERNAL, ++ "No UID for object [%s], perhaps mpg\n", fqname); ++ } + ret = ENOENT; + goto done; + } +@@ -1309,7 +1325,7 @@ ipa_get_ad_acct_ad_part_done(struct tevent_req *subreq) + + state->object_sid = talloc_strdup(state, sid); + if (state->object_sid == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup failed.\n"); + ret = ENOMEM; + goto fail; + } +@@ -1521,7 +1537,7 @@ static errno_t ipa_get_ad_apply_override_step(struct tevent_req *req) + + state->ar->filter_value = talloc_strdup(state->ar, obj_name); + if (state->ar->filter_value == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup failed.\n"); + return ENOMEM; + } + state->ar->filter_type = BE_FILTER_NAME; +diff --git a/src/providers/ipa/ipa_subdomains_server.c b/src/providers/ipa/ipa_subdomains_server.c +index fcdd05322..deb2c2cee 100644 +--- a/src/providers/ipa/ipa_subdomains_server.c ++++ b/src/providers/ipa/ipa_subdomains_server.c +@@ -513,7 +513,7 @@ static void ipa_getkeytab_exec(const char *ccache, + + gkt_env[0] = talloc_asprintf(NULL, "KRB5CCNAME=%s", ccache); + if (gkt_env[0] == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Failed to format KRB5CCNAME\n"); ++ DEBUG(SSSDBG_FATAL_FAILURE, "Failed to format KRB5CCNAME\n"); + exit(1); + } + +@@ -522,7 +522,7 @@ static void ipa_getkeytab_exec(const char *ccache, + ret = unlink(keytab_path); + if (ret == -1) { + ret = errno; +- DEBUG(SSSDBG_CRIT_FAILURE, ++ DEBUG(SSSDBG_FATAL_FAILURE, + "Failed to unlink the temporary ccname [%d][%s]\n", + ret, sss_strerror(ret)); + exit(1); +@@ -533,12 +533,12 @@ static void ipa_getkeytab_exec(const char *ccache, + "-r", "-s", server, "-p", principal, "-k", keytab_path, NULL, + gkt_env); + +- DEBUG(SSSDBG_CRIT_FAILURE, ++ DEBUG(SSSDBG_FATAL_FAILURE, + "execle returned %d, this shouldn't happen!\n", ret); + + /* The child should never end up here */ + ret = errno; +- DEBUG(SSSDBG_CRIT_FAILURE, ++ DEBUG(SSSDBG_FATAL_FAILURE, + "execle failed [%d][%s].\n", ret, sss_strerror(ret)); + exit(1); + } +@@ -748,7 +748,8 @@ static errno_t ipa_server_trusted_dom_setup_1way(struct tevent_req *req) + + state->new_keytab = talloc_asprintf(state, "%sXXXXXX", state->keytab); + if (state->new_keytab == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Cannot set up ipa_get_keytab\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Cannot set up ipa_get_keytab. talloc_asprintf() failed\n"); + return ENOMEM; + } + +diff --git a/src/providers/ipa/ipa_sudo.c b/src/providers/ipa/ipa_sudo.c +index 931770922..1b881d085 100644 +--- a/src/providers/ipa/ipa_sudo.c ++++ b/src/providers/ipa/ipa_sudo.c +@@ -223,7 +223,7 @@ ipa_sudo_init_ipa_schema(TALLOC_CTX *mem_ctx, + ipa_sudorule_map, IPA_OPTS_SUDORULE, + &sudo_ctx->sudorule_map); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse attribute map " ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse attribute map (rule) " + "[%d]: %s\n", ret, sss_strerror(ret)); + goto done; + } +@@ -232,7 +232,7 @@ ipa_sudo_init_ipa_schema(TALLOC_CTX *mem_ctx, + ipa_sudocmdgroup_map, IPA_OPTS_SUDOCMDGROUP, + &sudo_ctx->sudocmdgroup_map); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse attribute map " ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse attribute map (cmdgroup) " + "[%d]: %s\n", ret, sss_strerror(ret)); + goto done; + } +@@ -241,7 +241,7 @@ ipa_sudo_init_ipa_schema(TALLOC_CTX *mem_ctx, + ipa_sudocmd_map, IPA_OPTS_SUDOCMD, + &sudo_ctx->sudocmd_map); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse attribute map " ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse attribute map (cmd) " + "[%d]: %s\n", ret, sss_strerror(ret)); + goto done; + } +@@ -250,16 +250,16 @@ ipa_sudo_init_ipa_schema(TALLOC_CTX *mem_ctx, + CONFDB_SUDO_THRESHOLD, CONFDB_DEFAULT_SUDO_THRESHOLD, + &sudo_ctx->sudocmd_threshold); + if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, "Could not parse sudo search base\n"); +- return ret; ++ DEBUG(SSSDBG_CRIT_FAILURE, "Could not get sudo threshold\n"); ++ goto done; + } + + ret = sdap_parse_search_base(sudo_ctx, sudo_ctx->sdap_opts->basic, + SDAP_SUDO_SEARCH_BASE, + &sudo_ctx->sudo_sb); + if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, "Could not parse sudo search base\n"); +- return ret; ++ DEBUG(SSSDBG_CRIT_FAILURE, "Could not parse sudo search base\n"); ++ goto done; + } + + ret = ipa_sudo_ptask_setup(be_ctx, sudo_ctx); +diff --git a/src/providers/ipa/ipa_sudo_async.c b/src/providers/ipa/ipa_sudo_async.c +index 1d7a69814..c531ecbf9 100644 +--- a/src/providers/ipa/ipa_sudo_async.c ++++ b/src/providers/ipa/ipa_sudo_async.c +@@ -520,7 +520,7 @@ ipa_sudo_fetch_addtl_cmdgroups_done(struct tevent_req *subreq) + goto done; + } + +- DEBUG(SSSDBG_IMPORTANT_INFO, "Received %zu additional command groups\n", ++ DEBUG(SSSDBG_FUNC_DATA, "Received %zu additional command groups\n", + num_attrs); + + ret = ipa_sudo_filter_rules_bycmdgroups(state, state->domain, attrs, +@@ -609,7 +609,7 @@ ipa_sudo_fetch_rules_done(struct tevent_req *subreq) + goto done; + } + +- DEBUG(SSSDBG_IMPORTANT_INFO, "Received %zu sudo rules\n", num_attrs); ++ DEBUG(SSSDBG_FUNC_DATA, "Received %zu sudo rules\n", num_attrs); + + ret = ipa_sudo_conv_rules(state->conv, attrs, num_attrs); + if (ret != EOK) { +@@ -689,7 +689,7 @@ ipa_sudo_fetch_cmdgroups_done(struct tevent_req *subreq) + goto done; + } + +- DEBUG(SSSDBG_IMPORTANT_INFO, "Received %zu sudo command groups\n", ++ DEBUG(SSSDBG_FUNC_DATA, "Received %zu sudo command groups\n", + num_attrs); + + ret = ipa_sudo_conv_cmdgroups(state->conv, attrs, num_attrs); +@@ -769,7 +769,7 @@ ipa_sudo_fetch_cmds_done(struct tevent_req *subreq) + goto done; + } + +- DEBUG(SSSDBG_IMPORTANT_INFO, "Received %zu sudo commands\n", num_attrs); ++ DEBUG(SSSDBG_FUNC_DATA, "Received %zu sudo commands\n", num_attrs); + + ret = ipa_sudo_conv_cmds(state->conv, attrs, num_attrs); + if (ret != EOK) { +@@ -1109,7 +1109,7 @@ done: + if (in_transaction) { + sret = sysdb_transaction_cancel(state->sysdb); + if (sret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, "Could not cancel transaction\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "Could not cancel transaction\n"); + } + } + +diff --git a/src/providers/ipa/ipa_sudo_conversion.c b/src/providers/ipa/ipa_sudo_conversion.c +index b5fc49379..bd1ec72b3 100644 +--- a/src/providers/ipa/ipa_sudo_conversion.c ++++ b/src/providers/ipa/ipa_sudo_conversion.c +@@ -801,7 +801,7 @@ convert_host(TALLOC_CTX *mem_ctx, + *skip_entry = true; + return NULL; + } else if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, "ipa_get_rdn() failed on value %s [%d]: %s\n", ++ DEBUG(SSSDBG_CRIT_FAILURE, "ipa_get_rdn() failed on value %s [%d]: %s\n", + value, ret, sss_strerror(ret)); + return NULL; + } +@@ -841,7 +841,7 @@ convert_user(TALLOC_CTX *mem_ctx, + *skip_entry = true; + return NULL; + } else if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, "ipa_get_rdn() failed on value %s [%d]: %s\n", ++ DEBUG(SSSDBG_CRIT_FAILURE, "ipa_get_rdn() failed on value %s [%d]: %s\n", + value, ret, sss_strerror(ret)); + return NULL; + } +@@ -904,7 +904,7 @@ convert_group(TALLOC_CTX *mem_ctx, + *skip_entry = true; + return NULL; + } else if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, "ipa_get_rdn() failed on value %s [%d]: %s\n", ++ DEBUG(SSSDBG_CRIT_FAILURE, "ipa_get_rdn() failed on value %s [%d]: %s\n", + value, ret, sss_strerror(ret)); + return NULL; + } +diff --git a/src/providers/ipa/ipa_views.c b/src/providers/ipa/ipa_views.c +index 2a918bdc8..e1090d03b 100644 +--- a/src/providers/ipa/ipa_views.c ++++ b/src/providers/ipa/ipa_views.c +@@ -232,7 +232,7 @@ static errno_t get_dp_id_data_for_xyz(TALLOC_CTX *mem_ctx, const char *val, + ar->filter_value = talloc_strdup(ar, val); + ar->domain = talloc_strdup(ar, domain_name); + if (ar->filter_value == NULL || ar->domain == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup failed.\n"); + talloc_free(ar); + return ENOMEM; + } +@@ -471,7 +471,7 @@ static void ipa_get_ad_override_done(struct tevent_req *subreq) + + ret = ipa_get_ad_override_qualify_name(state); + if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, "Cannot qualify object name\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "Cannot qualify object name\n"); + goto fail; + } + +diff --git a/src/providers/krb5/krb5_access.c b/src/providers/krb5/krb5_access.c +index be9068c0f..2ae5abe14 100644 +--- a/src/providers/krb5/krb5_access.c ++++ b/src/providers/krb5/krb5_access.c +@@ -78,7 +78,8 @@ struct tevent_req *krb5_access_send(TALLOC_CTX *mem_ctx, + } + + if (pd->cmd != SSS_PAM_ACCT_MGMT) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected pam task.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Unexpected pam task %d.\n", pd->cmd); + ret = EINVAL; + goto done; + } +diff --git a/src/providers/krb5/krb5_auth.c b/src/providers/krb5/krb5_auth.c +index a1c0b3640..699c2467b 100644 +--- a/src/providers/krb5/krb5_auth.c ++++ b/src/providers/krb5/krb5_auth.c +@@ -499,7 +499,7 @@ struct tevent_req *krb5_auth_send(TALLOC_CTX *mem_ctx, + /* handle empty password gracefully */ + if (authtok_type == SSS_AUTHTOK_TYPE_EMPTY) { + DEBUG(SSSDBG_CRIT_FAILURE, +- "Illegal zero-length authtok for user [%s]\n", ++ "Illegal empty authtok for user [%s]\n", + pd->user); + state->pam_status = PAM_AUTH_ERR; + state->dp_err = DP_ERR_OK; +@@ -854,7 +854,7 @@ static void krb5_auth_done(struct tevent_req *subreq) + ret = EOK; + goto done; + default: +- DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected PAM task\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected PAM task %d\n", pd->cmd); + ret = EINVAL; + goto done; + } +diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c +index cab7b27a2..06fdf7156 100644 +--- a/src/providers/krb5/krb5_child.c ++++ b/src/providers/krb5/krb5_child.c +@@ -258,7 +258,7 @@ static void sss_krb5_expire_callback_func(krb5_context context, void *data, + + blob = talloc_array(kr->pd, uint32_t, 2); + if (blob == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "talloc_size failed.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_array failed.\n"); + return; + } + +@@ -525,7 +525,8 @@ static krb5_error_code tokeninfo_matches(TALLOC_CTX *mem_ctx, + out_token, out_pin); + break; + default: +- DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported authtok type.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Unsupported authtok type %d\n", sss_authtok_get_type(auth_tok)); + } + + return EINVAL; +@@ -1087,7 +1088,7 @@ static errno_t pack_response_packet(TALLOC_CTX *mem_ctx, errno_t error, + + buf = talloc_array(mem_ctx, uint8_t, size); + if (!buf) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Insufficient memory to create message.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_array failed\n"); + return ENOMEM; + } + +@@ -1958,13 +1959,12 @@ static errno_t changepw_child(struct krb5_req *kr, bool prelim) + &msg_len, &msg); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, +- "pack_user_info_chpass_error failed.\n"); ++ "pack_user_info_chpass_error failed [%d]\n", ret); + } else { + ret = pam_add_response(kr->pd, SSS_PAM_USER_INFO, msg_len, + msg); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, +- "pam_add_response failed.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n"); + } + } + return kerr; +@@ -2036,13 +2036,12 @@ static errno_t changepw_child(struct krb5_req *kr, bool prelim) + &user_resp_len, &user_resp); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, +- "pack_user_info_chpass_error failed.\n"); ++ "pack_user_info_chpass_error failed [%d]\n", ret); + } else { + ret = pam_add_response(kr->pd, SSS_PAM_USER_INFO, user_resp_len, + user_resp); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, +- "pam_add_response failed.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n"); + } + } + } +@@ -2448,7 +2447,7 @@ static errno_t unpack_buffer(uint8_t *buf, size_t size, + + pd = create_pam_data(kr); + if (pd == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "create_pam_data failed.\n"); + return ENOMEM; + } + kr->pd = pd; +@@ -3110,7 +3109,7 @@ static int k5c_setup(struct krb5_req *kr, uint32_t offline) + + kr->creds = calloc(1, sizeof(krb5_creds)); + if (kr->creds == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "calloc failed.\n"); + return ENOMEM; + } + +@@ -3345,7 +3344,7 @@ int main(int argc, const char *argv[]) + + kr = talloc_zero(NULL, struct krb5_req); + if (kr == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "talloc failed.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n"); + ret = ENOMEM; + goto done; + } +@@ -3403,7 +3402,7 @@ int main(int argc, const char *argv[]) + + ret = k5c_setup(kr, offline); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "krb5_child_setup failed.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "k5c_setup failed.\n"); + goto done; + } + +diff --git a/src/providers/krb5/krb5_child_handler.c b/src/providers/krb5/krb5_child_handler.c +index 37f4304e8..01777e22b 100644 +--- a/src/providers/krb5/krb5_child_handler.c ++++ b/src/providers/krb5/krb5_child_handler.c +@@ -449,14 +449,14 @@ static errno_t fork_child(struct tevent_req *req) + if (ret == -1) { + ret = errno; + DEBUG(SSSDBG_CRIT_FAILURE, +- "pipe failed [%d][%s].\n", errno, strerror(errno)); ++ "pipe (from) failed [%d][%s].\n", errno, strerror(errno)); + goto fail; + } + ret = pipe(pipefd_to_child); + if (ret == -1) { + ret = errno; + DEBUG(SSSDBG_CRIT_FAILURE, +- "pipe failed [%d][%s].\n", errno, strerror(errno)); ++ "pipe (to) failed [%d][%s].\n", errno, strerror(errno)); + goto fail; + } + +diff --git a/src/providers/krb5/krb5_common.c b/src/providers/krb5/krb5_common.c +index 5c11c347b..316603946 100644 +--- a/src/providers/krb5/krb5_common.c ++++ b/src/providers/krb5/krb5_common.c +@@ -793,7 +793,7 @@ static void krb5_resolve_callback(void *private_data, struct fo_server *server) + + krb5_service = talloc_get_type(private_data, struct krb5_service); + if (!krb5_service) { +- DEBUG(SSSDBG_CRIT_FAILURE, "FATAL: Bad private_data\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "Bad private_data\n"); + return; + } + +@@ -1110,7 +1110,7 @@ void remove_krb5_info_files_callback(void *pvt) + ctx->kdc_service_name); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, +- "be_fo_run_callbacks_at_next_request failed, " ++ "be_fo_run_callbacks_at_next_request(kdc_service_name) failed, " + "krb5 info files will not be removed, because " + "it is unclear if they will be recreated properly.\n"); + return; +@@ -1120,7 +1120,7 @@ void remove_krb5_info_files_callback(void *pvt) + ctx->kpasswd_service_name); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, +- "be_fo_run_callbacks_at_next_request failed, " ++ "be_fo_run_callbacks_at_next_request(kpasswd_service_name) failed, " + "krb5 info files will not be removed, because " + "it is unclear if they will be recreated properly.\n"); + return; +diff --git a/src/providers/krb5/krb5_delayed_online_authentication.c b/src/providers/krb5/krb5_delayed_online_authentication.c +index 8572d1249..07d375b9d 100644 +--- a/src/providers/krb5/krb5_delayed_online_authentication.c ++++ b/src/providers/krb5/krb5_delayed_online_authentication.c +@@ -173,7 +173,7 @@ static errno_t authenticate_stored_users( + ret = hash_lookup(uid_table, &key, &value); + + if (ret == HASH_SUCCESS) { +- DEBUG(SSSDBG_CRIT_FAILURE, "User [%s] is still logged in, " ++ DEBUG(SSSDBG_FUNC_DATA, "User [%s] is still logged in, " + "trying online authentication.\n", pd->user); + + auth_data = talloc_zero(deferred_auth_ctx->be_ctx, +@@ -193,7 +193,7 @@ static errno_t authenticate_stored_users( + } + } + } else { +- DEBUG(SSSDBG_CRIT_FAILURE, "User [%s] is not logged in anymore, " ++ DEBUG(SSSDBG_FUNC_DATA, "User [%s] is not logged in anymore, " + "discarding online authentication.\n", pd->user); + talloc_free(pd); + } +diff --git a/src/providers/krb5/krb5_renew_tgt.c b/src/providers/krb5/krb5_renew_tgt.c +index 8b2159e92..d79e7c367 100644 +--- a/src/providers/krb5/krb5_renew_tgt.c ++++ b/src/providers/krb5/krb5_renew_tgt.c +@@ -405,7 +405,7 @@ static errno_t check_ccache_files(struct renew_tgt_ctx *renew_tgt_ctx) + + base_dn = sysdb_user_base_dn(tmp_ctx, renew_tgt_ctx->be_ctx->domain); + if (base_dn == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, "sysdb_base_dn failed.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_base_dn failed.\n"); + ret = ENOMEM; + goto done; + } +@@ -440,7 +440,7 @@ static errno_t check_ccache_files(struct renew_tgt_ctx *renew_tgt_ctx) + + ret = sss_parse_internal_fqname(tmp_ctx, user_name, NULL, &user_dom); + if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, ++ DEBUG(SSSDBG_CRIT_FAILURE, + "Cannot parse internal fqname [%d]: %s\n", + ret, sss_strerror(ret)); + goto done; +diff --git a/src/providers/krb5/krb5_utils.c b/src/providers/krb5/krb5_utils.c +index e3f8f2140..43056ba28 100644 +--- a/src/providers/krb5/krb5_utils.c ++++ b/src/providers/krb5/krb5_utils.c +@@ -287,7 +287,7 @@ char *expand_ccname_template(TALLOC_CTX *mem_ctx, struct krb5child_req *kr, + name = sss_output_name(tmp_ctx, kr->pd->user, case_sensitive, 0); + if (name == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, +- "sss_get_cased_name failed\n"); ++ "sss_output_name failed\n"); + goto done; + } + +diff --git a/src/providers/ldap/ldap_auth.c b/src/providers/ldap/ldap_auth.c +index 89ff4ece0..42ef962b4 100644 +--- a/src/providers/ldap/ldap_auth.c ++++ b/src/providers/ldap/ldap_auth.c +@@ -64,7 +64,7 @@ static errno_t add_expired_warning(struct pam_data *pd, long exp_time) + + data = talloc_array(pd, uint32_t, 2); + if (data == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "talloc_size failed.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_array failed.\n"); + return ENOMEM; + } + +@@ -249,7 +249,8 @@ errno_t check_pwexpire_policy(enum pwexpire pw_expire_type, + ret = EOK; + break; + default: +- DEBUG(SSSDBG_CRIT_FAILURE, "Unknown password expiration type.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Unknown password expiration type %d.\n", pw_expire_type); + ret = EINVAL; + } + +@@ -1355,9 +1356,10 @@ static void sdap_pam_chpass_handler_auth_done(struct tevent_req *subreq) + case PWEXPIRE_NONE: + break; + default: +- DEBUG(SSSDBG_CRIT_FAILURE, "Unknown password expiration type.\n"); +- state->pd->pam_status = PAM_SYSTEM_ERR; +- goto done; ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Unknown password expiration type %d.\n", pw_expire_type); ++ state->pd->pam_status = PAM_SYSTEM_ERR; ++ goto done; + } + } + +diff --git a/src/providers/ldap/ldap_child.c b/src/providers/ldap/ldap_child.c +index 84941c6e4..8580e2785 100644 +--- a/src/providers/ldap/ldap_child.c ++++ b/src/providers/ldap/ldap_child.c +@@ -223,7 +223,7 @@ static int lc_verify_keytab_ex(const char *principal, + /* This should never happen. The API docs for this function + * specify only success for this function + */ +- DEBUG(SSSDBG_CRIT_FAILURE,"Could not free keytab entry contents\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "Could not free keytab entry contents\n"); + /* This is non-fatal, so we'll continue here */ + } + +diff --git a/src/providers/ldap/ldap_init.c b/src/providers/ldap/ldap_init.c +index cd589a7c0..2ad8680a1 100644 +--- a/src/providers/ldap/ldap_init.c ++++ b/src/providers/ldap/ldap_init.c +@@ -43,8 +43,8 @@ struct ldap_init_ctx { + }; + + /* Please use this only for short lists */ +-errno_t check_order_list_for_duplicates(char **list, +- bool case_sensitive) ++static errno_t check_order_list_for_duplicates(char **list, ++ bool case_sensitive) + { + size_t c; + size_t d; +diff --git a/src/providers/ldap/ldap_options.c b/src/providers/ldap/ldap_options.c +index d06d3980e..bb51785fb 100644 +--- a/src/providers/ldap/ldap_options.c ++++ b/src/providers/ldap/ldap_options.c +@@ -408,14 +408,15 @@ int ldap_get_options(TALLOC_CTX *memctx, + sss_erase_talloc_mem_securely(cleartext); + talloc_free(cleartext); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "dp_opt_set_string failed.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "dp_opt_set_blob(authtok) failed.\n"); + goto done; + } + + ret = dp_opt_set_string(opts->basic, SDAP_DEFAULT_AUTHTOK_TYPE, + "password"); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "dp_opt_set_string failed.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "dp_opt_set_string(authtok_type) failed.\n"); + goto done; + } + } +@@ -629,7 +630,8 @@ int ldap_get_autofs_options(TALLOC_CTX *memctx, + default_entry_map = rfc2307bis_autofs_entry_map; + break; + default: +- DEBUG(SSSDBG_CRIT_FAILURE, "Unknown LDAP schema!\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Unknown LDAP schema %d!\n", opts->schema_type); + return EINVAL; + } + +diff --git a/src/providers/ldap/sdap.c b/src/providers/ldap/sdap.c +index 7cb00480d..32c0144b9 100644 +--- a/src/providers/ldap/sdap.c ++++ b/src/providers/ldap/sdap.c +@@ -371,7 +371,7 @@ int sdap_get_map(TALLOC_CTX *memctx, + + if (map[i].def_name && !map[i].name) { + DEBUG(SSSDBG_CRIT_FAILURE, +- "Failed to retrieve value for %s\n", map[i].opt_name); ++ "Failed to process value for %s\n", map[i].opt_name); + talloc_zfree(map); + return EINVAL; + } +@@ -532,7 +532,8 @@ int sdap_parse_entry(TALLOC_CTX *memctx, + if (!vals) { + ldap_get_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno); + if (lerrno != LDAP_SUCCESS) { +- DEBUG(SSSDBG_CRIT_FAILURE, "LDAP Library error: %d(%s)\n", ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "ldap_get_values_len() failed: %d(%s)\n", + lerrno, sss_ldap_err2string(lerrno)); + ret = EIO; + goto done; +@@ -613,7 +614,7 @@ int sdap_parse_entry(TALLOC_CTX *memctx, + + ldap_get_option(sh->ldap, LDAP_OPT_RESULT_CODE, &lerrno); + if (lerrno) { +- DEBUG(SSSDBG_CRIT_FAILURE, "LDAP Library error: %d(%s)\n", ++ DEBUG(SSSDBG_CRIT_FAILURE, "ldap_get_option() failed: %d(%s)\n", + lerrno, sss_ldap_err2string(lerrno)); + ret = EIO; + goto done; +@@ -884,7 +885,8 @@ errno_t setup_tls_config(struct dp_option *basic_opts) + ldap_opt_x_tls_require_cert = LDAP_OPT_X_TLS_HARD; + } + else { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unknown value for tls_reqcert.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Unknown value for tls_reqcert '%s'.\n", tls_opt); + return EINVAL; + } + /* LDAP_OPT_X_TLS_REQUIRE_CERT has to be set as a global option, +@@ -893,7 +895,8 @@ errno_t setup_tls_config(struct dp_option *basic_opts) + &ldap_opt_x_tls_require_cert); + if (ret != LDAP_OPT_SUCCESS) { + DEBUG(SSSDBG_CRIT_FAILURE, +- "ldap_set_option failed: %s\n", sss_ldap_err2string(ret)); ++ "ldap_set_option(req_cert) failed: %s\n", ++ sss_ldap_err2string(ret)); + return EIO; + } + } +@@ -903,7 +906,8 @@ errno_t setup_tls_config(struct dp_option *basic_opts) + ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, tls_opt); + if (ret != LDAP_OPT_SUCCESS) { + DEBUG(SSSDBG_CRIT_FAILURE, +- "ldap_set_option failed: %s\n", sss_ldap_err2string(ret)); ++ "ldap_set_option(cacertfile) failed: %s\n", ++ sss_ldap_err2string(ret)); + return EIO; + } + } +@@ -913,7 +917,8 @@ errno_t setup_tls_config(struct dp_option *basic_opts) + ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTDIR, tls_opt); + if (ret != LDAP_OPT_SUCCESS) { + DEBUG(SSSDBG_CRIT_FAILURE, +- "ldap_set_option failed: %s\n", sss_ldap_err2string(ret)); ++ "ldap_set_option(cacertdir) failed: %s\n", ++ sss_ldap_err2string(ret)); + return EIO; + } + } +@@ -923,7 +928,8 @@ errno_t setup_tls_config(struct dp_option *basic_opts) + ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CERTFILE, tls_opt); + if (ret != LDAP_OPT_SUCCESS) { + DEBUG(SSSDBG_CRIT_FAILURE, +- "ldap_set_option failed: %s\n", sss_ldap_err2string(ret)); ++ "ldap_set_option(certfile) failed: %s\n", ++ sss_ldap_err2string(ret)); + return EIO; + } + } +@@ -933,7 +939,8 @@ errno_t setup_tls_config(struct dp_option *basic_opts) + ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_KEYFILE, tls_opt); + if (ret != LDAP_OPT_SUCCESS) { + DEBUG(SSSDBG_CRIT_FAILURE, +- "ldap_set_option failed: %s\n", sss_ldap_err2string(ret)); ++ "ldap_set_option(keyfile) failed: %s\n", ++ sss_ldap_err2string(ret)); + return EIO; + } + } +@@ -943,7 +950,8 @@ errno_t setup_tls_config(struct dp_option *basic_opts) + ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CIPHER_SUITE, tls_opt); + if (ret != LDAP_OPT_SUCCESS) { + DEBUG(SSSDBG_CRIT_FAILURE, +- "ldap_set_option failed: %s\n", sss_ldap_err2string(ret)); ++ "ldap_set_option(cipher) failed: %s\n", ++ sss_ldap_err2string(ret)); + return EIO; + } + } +diff --git a/src/providers/ldap/sdap_access.c b/src/providers/ldap/sdap_access.c +index dd04ec512..8add97ba8 100644 +--- a/src/providers/ldap/sdap_access.c ++++ b/src/providers/ldap/sdap_access.c +@@ -317,7 +317,8 @@ static errno_t sdap_access_check_next_rule(struct sdap_access_req_ctx *state, + + default: + DEBUG(SSSDBG_CRIT_FAILURE, +- "Unexpected access rule type. Access denied.\n"); ++ "Unexpected access rule type %d. Access denied.\n", ++ state->access_ctx->access_rule[state->current_rule]); + ret = ERR_ACCESS_DENIED; + } + +@@ -1220,13 +1221,13 @@ static errno_t sdap_save_user_cache_bool(struct sss_domain_info *domain, + attrs = sysdb_new_attrs(NULL); + if (attrs == NULL) { + ret = ENOMEM; +- DEBUG(SSSDBG_CRIT_FAILURE, "Could not set up attrs\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "Could not create attrs\n"); + goto done; + } + + ret = sysdb_attrs_add_bool(attrs, attr_name, value); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Could not set up attrs\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "Could not set up attr value\n"); + goto done; + } + +@@ -1787,7 +1788,7 @@ errno_t sdap_access_ppolicy_step(struct tevent_req *req) + false); + + if (subreq == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "sdap_access_ppolicy_send failed.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "sdap_get_generic_send failed.\n"); + ret = ENOMEM; + goto done; + } +@@ -1913,7 +1914,7 @@ static void sdap_access_ppolicy_step_done(struct tevent_req *subreq) + ret = sdap_access_decide_offline(state->cached_access); + } else { + DEBUG(SSSDBG_CRIT_FAILURE, +- "sdap_get_generic_send() returned error [%d][%s]\n", ++ "sdap_id_op_done() returned error [%d][%s]\n", + ret, sss_strerror(ret)); + } + +diff --git a/src/providers/ldap/sdap_async.c b/src/providers/ldap/sdap_async.c +index 68d5d44f8..cc77fb249 100644 +--- a/src/providers/ldap/sdap_async.c ++++ b/src/providers/ldap/sdap_async.c +@@ -749,7 +749,7 @@ sdap_modify_send(TALLOC_CTX *mem_ctx, + + ret = ldap_modify_ext(state->sh->ldap, dn, mods, NULL, NULL, &msgid); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Failed to send operation!\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "ldap_modify_ext() failed [%d]\n", ret); + goto done; + } + +@@ -2120,7 +2120,7 @@ static int sdap_x_deref_create_control(struct sdap_handle *sh, + + ret = ldap_create_deref_control_value(sh->ldap, ds, &derefval); + if (ret != LDAP_SUCCESS) { +- DEBUG(SSSDBG_CRIT_FAILURE, "sss_ldap_control_create failed: %s\n", ++ DEBUG(SSSDBG_CRIT_FAILURE, "ldap_create_deref_control_value failed: %s\n", + ldap_err2string(ret)); + return ret; + } +@@ -2129,7 +2129,7 @@ static int sdap_x_deref_create_control(struct sdap_handle *sh, + 1, &derefval, 1, ctrl); + ldap_memfree(derefval.bv_val); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "sss_ldap_control_create failed\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "sdap_control_create failed %d\n", ret); + return ret; + } + +@@ -2875,7 +2875,8 @@ static void sdap_deref_search_done(struct tevent_req *subreq) + &state->reply_count, &state->reply); + break; + default: +- DEBUG(SSSDBG_CRIT_FAILURE, "Unknown deref method\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, ++ "Unknown deref method %d\n", state->deref_type); + tevent_req_error(req, EINVAL); + return; + } +diff --git a/src/providers/ldap/sdap_async_autofs.c b/src/providers/ldap/sdap_async_autofs.c +index eaca0324e..ae2fa33e1 100644 +--- a/src/providers/ldap/sdap_async_autofs.c ++++ b/src/providers/ldap/sdap_async_autofs.c +@@ -720,7 +720,7 @@ sdap_autofs_setautomntent_send(TALLOC_CTX *memctx, + dp_opt_get_int(state->opts->basic, + SDAP_SEARCH_TIMEOUT)); + if (!subreq) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "sdap_get_automntmap_send failed\n"); + ret = ENOMEM; + goto fail; + } +diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c +index 5f69cedcc..eead3f119 100644 +--- a/src/providers/ldap/sdap_async_connection.c ++++ b/src/providers/ldap/sdap_async_connection.c +@@ -694,10 +694,10 @@ static struct tevent_req *simple_bind_send(TALLOC_CTX *memctx, + LDAP_OPT_RESULT_CODE, &ldap_err); + if (ret != LDAP_OPT_SUCCESS) { + DEBUG(SSSDBG_CRIT_FAILURE, +- "ldap_bind failed (couldn't get ldap error)\n"); ++ "ldap_sasl_bind failed (couldn't get ldap error)\n"); + ret = LDAP_LOCAL_ERROR; + } else { +- DEBUG(SSSDBG_CRIT_FAILURE, "ldap_bind failed (%d)[%s]\n", ++ DEBUG(SSSDBG_CRIT_FAILURE, "ldap_sasl_bind failed (%d)[%s]\n", + ldap_err, sss_ldap_err2string(ldap_err)); + ret = ldap_err; + } +@@ -988,7 +988,7 @@ static struct tevent_req *sasl_bind_send(TALLOC_CTX *memctx, + (*sdap_sasl_interact), state); + if (ret != LDAP_SUCCESS) { + DEBUG(SSSDBG_CRIT_FAILURE, +- "ldap_sasl_bind failed (%d)[%s]\n", ++ "ldap_sasl_interactive_bind_s failed (%d)[%s]\n", + ret, sss_ldap_err2string(ret)); + + optret = sss_ldap_get_diagnostic_msg(state, state->sh->ldap, +diff --git a/src/providers/ldap/sdap_async_groups.c b/src/providers/ldap/sdap_async_groups.c +index 5dbfd73c4..16c4a5f37 100644 +--- a/src/providers/ldap/sdap_async_groups.c ++++ b/src/providers/ldap/sdap_async_groups.c +@@ -883,10 +883,7 @@ static int sdap_save_grpmem(TALLOC_CTX *memctx, + const char *check_name; + + if (dom->ignore_group_members) { +- DEBUG(SSSDBG_CRIT_FAILURE, +- "Group members are ignored, nothing to do. If you see this " \ +- "message it might indicate an error in the group processing " \ +- "logic.\n"); ++ DEBUG(SSSDBG_TRACE_FUNC, "Group members are ignored, nothing to do.\n"); + return EOK; + } + +@@ -978,7 +975,12 @@ static int sdap_save_grpmem(TALLOC_CTX *memctx, + ret = sysdb_remove_attrs(group_dom, group_name, SYSDB_MEMBER_GROUP, + discard_const(remove_attrs)); + if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, "sysdb_remove_attrs failed.\n"); ++ if (ret != ENOENT) { ++ DEBUG(SSSDBG_OP_FAILURE, "sysdb_remove_attrs failed.\n"); ++ } else { ++ DEBUG(SSSDBG_MINOR_FAILURE, ++ "sysdb_remove_attrs failed for missing entry\n"); ++ } + goto fail; + } + } else { +@@ -1014,7 +1016,7 @@ static int sdap_save_grpmem(TALLOC_CTX *memctx, + return EOK; + + fail: +- DEBUG(SSSDBG_OP_FAILURE, ++ DEBUG(SSSDBG_MINOR_FAILURE, + "Failed to save members of group %s\n", group_name); + return ret; + } +@@ -1130,8 +1132,13 @@ static int sdap_save_groups(TALLOC_CTX *memctx, + /* Do not fail completely on errors. + * Just report the failure to save and go on */ + if (ret) { +- DEBUG(SSSDBG_OP_FAILURE, +- "Failed to store group %d members.\n", i); ++ if (ret != ENOENT) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "Failed to store group %d members: %d\n", i, ret); ++ } else { ++ DEBUG(SSSDBG_FUNC_DATA, ++ "Can't save members of missing group %d\n", i); ++ } + } else { + DEBUG(SSSDBG_TRACE_ALL, "Group %d members processed!\n", i); + } +@@ -1270,7 +1277,7 @@ sdap_process_group_send(TALLOC_CTX *memctx, + + /* Group without members */ + if (el->num_values == 0) { +- DEBUG(SSSDBG_OP_FAILURE, "No Members. Done!\n"); ++ DEBUG(SSSDBG_FUNC_DATA, "No Members. Done!\n"); + ret = EOK; + goto done; + } +@@ -2249,7 +2256,7 @@ static void sdap_nested_done(struct tevent_req *subreq) + + if (hash_count(state->missing_external) == 0) { + /* No external members. Processing complete */ +- DEBUG(SSSDBG_TRACE_INTERNAL, "No external members, done"); ++ DEBUG(SSSDBG_TRACE_INTERNAL, "No external members, done\n"); + tevent_req_done(req); + return; + } +diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c +index 4b5b36403..bf8f9482b 100644 +--- a/src/providers/ldap/sdap_async_initgroups.c ++++ b/src/providers/ldap/sdap_async_initgroups.c +@@ -345,7 +345,7 @@ int sdap_initgr_common_store(struct sysdb_ctx *sysdb, + add_groups, ldap_groups, + ldap_groups_count); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Adding incomplete users failed\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "Adding incomplete groups failed\n"); + goto done; + } + } +@@ -1043,6 +1043,10 @@ static void sdap_initgr_nested_search(struct tevent_req *subreq) + state->groups[state->groups_cur] = talloc_steal(state->groups, + groups[0]); + state->groups_cur++; ++ } else if (count == 0) { ++ /* this might be HBAC or sudo rule */ ++ DEBUG(SSSDBG_FUNC_DATA, "Object %s not found. Skipping\n", ++ state->group_dns[state->cur]); + } else { + DEBUG(SSSDBG_OP_FAILURE, + "Search for group %s, returned %zu results. Skipping\n", +diff --git a/src/providers/ldap/sdap_async_initgroups_ad.c b/src/providers/ldap/sdap_async_initgroups_ad.c +index eb3e779ed..80ac4c1f4 100644 +--- a/src/providers/ldap/sdap_async_initgroups_ad.c ++++ b/src/providers/ldap/sdap_async_initgroups_ad.c +@@ -378,7 +378,7 @@ static void sdap_ad_resolve_sids_done(struct tevent_req *subreq) + /* Group was not found, we will ignore the error and continue with + * next group. This may happen for example if the group is built-in, + * but a custom search base is provided. */ +- DEBUG(SSSDBG_CRIT_FAILURE, ++ DEBUG(SSSDBG_MINOR_FAILURE, + "Unable to resolve SID %s - will try next sid.\n", + state->current_sid); + } else if (ret != EOK || sdap_error != EOK || dp_error != DP_ERR_OK) { +diff --git a/src/providers/ldap/sdap_async_sudo.c b/src/providers/ldap/sdap_async_sudo.c +index 5473e1df8..28b65b639 100644 +--- a/src/providers/ldap/sdap_async_sudo.c ++++ b/src/providers/ldap/sdap_async_sudo.c +@@ -111,7 +111,7 @@ static void sdap_sudo_load_sudoers_done(struct tevent_req *subreq) + return; + } + +- DEBUG(SSSDBG_IMPORTANT_INFO, "Received %zu sudo rules\n", ++ DEBUG(SSSDBG_FUNC_DATA, "Received %zu sudo rules\n", + state->num_rules); + + tevent_req_done(req); +@@ -665,7 +665,7 @@ done: + if (in_transaction) { + sret = sysdb_transaction_cancel(state->sysdb); + if (sret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, "Could not cancel transaction\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "Could not cancel transaction\n"); + } + } + +diff --git a/src/providers/ldap/sdap_child_helpers.c b/src/providers/ldap/sdap_child_helpers.c +index 9d25aea8b..480efc41b 100644 +--- a/src/providers/ldap/sdap_child_helpers.c ++++ b/src/providers/ldap/sdap_child_helpers.c +@@ -95,14 +95,14 @@ static errno_t sdap_fork_child(struct tevent_context *ev, + if (ret == -1) { + ret = errno; + DEBUG(SSSDBG_CRIT_FAILURE, +- "pipe failed [%d][%s].\n", ret, strerror(ret)); ++ "pipe(from) failed [%d][%s].\n", ret, strerror(ret)); + goto fail; + } + ret = pipe(pipefd_to_child); + if (ret == -1) { + ret = errno; + DEBUG(SSSDBG_CRIT_FAILURE, +- "pipe failed [%d][%s].\n", ret, strerror(ret)); ++ "pipe(to) failed [%d][%s].\n", ret, strerror(ret)); + goto fail; + } + +@@ -332,7 +332,7 @@ struct tevent_req *sdap_get_tgt_send(TALLOC_CTX *mem_ctx, + + ret = set_tgt_child_timeout(req, ev, timeout); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "activate_child_timeout_handler failed.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "set_tgt_child_timeout failed.\n"); + goto fail; + } + +diff --git a/src/providers/ldap/sdap_hostid.c b/src/providers/ldap/sdap_hostid.c +index d90a83854..ae8caaddb 100644 +--- a/src/providers/ldap/sdap_hostid.c ++++ b/src/providers/ldap/sdap_hostid.c +@@ -166,7 +166,7 @@ hosts_get_done(struct tevent_req *subreq) + } + + if (state->count == 0) { +- DEBUG(SSSDBG_OP_FAILURE, ++ DEBUG(SSSDBG_FUNC_DATA, + "No host with name [%s] found.\n", state->name); + + ret = sysdb_delete_ssh_host(state->domain, state->name); +diff --git a/src/providers/ldap/sdap_id_op.c b/src/providers/ldap/sdap_id_op.c +index 6c803f31d..b8d76f8a5 100644 +--- a/src/providers/ldap/sdap_id_op.c ++++ b/src/providers/ldap/sdap_id_op.c +@@ -563,7 +563,7 @@ static void sdap_id_op_connect_done(struct tevent_req *subreq) + "is enabled.\n"); + } else { + /* be is going offline as there is no more servers to try */ +- DEBUG(SSSDBG_CRIT_FAILURE, ++ DEBUG(SSSDBG_OP_FAILURE, + "Failed to connect, going offline (%d [%s])\n", + ret, strerror(ret)); + is_offline = true; +diff --git a/src/providers/proxy/proxy_auth.c b/src/providers/proxy/proxy_auth.c +index 926ce98f4..0e6fc8ea8 100644 +--- a/src/providers/proxy/proxy_auth.c ++++ b/src/providers/proxy/proxy_auth.c +@@ -68,7 +68,7 @@ static struct tevent_req *proxy_child_send(TALLOC_CTX *mem_ctx, + + req = tevent_req_create(mem_ctx, &state, struct proxy_child_ctx); + if (req == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Could not send PAM request to child\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); + return NULL; + } + +@@ -391,7 +391,7 @@ static void proxy_child_init_done(struct tevent_req *subreq) { + */ + sig_ctx = talloc_zero(child_ctx->auth_ctx, struct proxy_child_sig_ctx); + if(sig_ctx == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "tevent_add_signal failed.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n"); + tevent_req_error(req, ENOMEM); + return; + } +@@ -753,7 +753,7 @@ proxy_pam_handler_send(TALLOC_CTX *mem_ctx, + pd->pam_status = PAM_SUCCESS; + goto immediately; + default: +- DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported PAM task.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported PAM task %d\n", pd->cmd); + pd->pam_status = PAM_MODULE_UNKNOWN; + goto immediately; + } +diff --git a/src/providers/proxy/proxy_child.c b/src/providers/proxy/proxy_child.c +index dc06f4669..bb96ec0f4 100644 +--- a/src/providers/proxy/proxy_child.c ++++ b/src/providers/proxy/proxy_child.c +@@ -270,7 +270,7 @@ static errno_t call_pam_stack(const char *pam_target, struct pam_data *pd) + } + break; + default: +- DEBUG(SSSDBG_CRIT_FAILURE, "unknown PAM call\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "unknown PAM call %d\n", pd->cmd); + pam_status=PAM_ABORT; + } + +@@ -383,13 +383,13 @@ proxy_cli_init(struct pc_ctx *ctx) + ret = sss_iface_connect_address(ctx, ctx->ev, sbus_cliname, sbus_address, + NULL, &ctx->conn); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to connect to %s\n", sbus_address); ++ DEBUG(SSSDBG_FATAL_FAILURE, "Unable to connect to %s\n", sbus_address); + goto done; + } + + ret = sbus_connection_add_path_map(ctx->conn, paths); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add paths [%d]: %s\n", ++ DEBUG(SSSDBG_FATAL_FAILURE, "Unable to add paths [%d]: %s\n", + ret, sss_strerror(ret)); + goto done; + } +@@ -580,7 +580,7 @@ int main(int argc, const char *argv[]) + return 3; + } + +- DEBUG(SSSDBG_CRIT_FAILURE, ++ DEBUG(SSSDBG_IMPORTANT_INFO, + "Proxy child for domain [%s] started!\n", domain); + + /* loop on main */ +diff --git a/src/providers/proxy/proxy_client.c b/src/providers/proxy/proxy_client.c +index 09ebf3bda..5a4fbcde1 100644 +--- a/src/providers/proxy/proxy_client.c ++++ b/src/providers/proxy/proxy_client.c +@@ -116,7 +116,7 @@ proxy_client_init(struct sbus_connection *conn, + + ret = sbus_connection_add_path_map(conn, paths); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add paths [%d]: %s\n", ++ DEBUG(SSSDBG_FATAL_FAILURE, "Unable to add paths [%d]: %s\n", + ret, sss_strerror(ret)); + } + +diff --git a/src/providers/proxy/proxy_id.c b/src/providers/proxy/proxy_id.c +index 82394862c..f36386089 100644 +--- a/src/providers/proxy/proxy_id.c ++++ b/src/providers/proxy/proxy_id.c +@@ -170,7 +170,7 @@ handle_getpw_result(enum nss_status status, struct passwd *pwd, + switch (status) { + case NSS_STATUS_NOTFOUND: + +- DEBUG(SSSDBG_MINOR_FAILURE, "User not found.\n"); ++ DEBUG(SSSDBG_TRACE_FUNC, "User not found.\n"); + *del_user = true; + break; + +@@ -979,9 +979,7 @@ static int get_gr_name(struct proxy_id_ctx *ctx, + grp = talloc(tmpctx, struct group); + if (!grp) { + ret = ENOMEM; +- DEBUG(SSSDBG_CRIT_FAILURE, +- "proxy -> getgrnam_r failed for '%s': [%d] %s\n", +- i_name, ret, strerror(ret)); ++ DEBUG(SSSDBG_CRIT_FAILURE, "talloc() failed\n"); + goto done; + } + +diff --git a/src/resolv/async_resolv.c b/src/resolv/async_resolv.c +index 07f05ff17..294a4b882 100644 +--- a/src/resolv/async_resolv.c ++++ b/src/resolv/async_resolv.c +@@ -177,7 +177,7 @@ add_timeout_timer(struct tevent_context *ev, struct resolv_ctx *ctx) + ctx->timeout_watcher = tevent_add_timer(ev, ctx, tv, check_fd_timeouts, + ctx); + if (ctx->timeout_watcher == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "tevent_add_timer() failed\n"); + } + } + +diff --git a/src/responder/autofs/autofssrv.c b/src/responder/autofs/autofssrv.c +index a802ed5d0..27de1b44a 100644 +--- a/src/responder/autofs/autofssrv.c ++++ b/src/responder/autofs/autofssrv.c +@@ -85,7 +85,7 @@ autofs_register_service_iface(struct autofs_ctx *autofs_ctx, + + ret = sbus_connection_add_path(rctx->mon_conn, SSS_BUS_PATH, &iface_svc); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to register service interface" ++ DEBUG(SSSDBG_FATAL_FAILURE, "Unable to register service interface" + "[%d]: %s\n", ret, sss_strerror(ret)); + } + +diff --git a/src/responder/autofs/autofssrv_cmd.c b/src/responder/autofs/autofssrv_cmd.c +index 6d51e75ac..7c8090993 100644 +--- a/src/responder/autofs/autofssrv_cmd.c ++++ b/src/responder/autofs/autofssrv_cmd.c +@@ -477,7 +477,7 @@ sss_autofs_cmd_setautomntent(struct cli_ctx *cli_ctx) + autofs_ctx->rctx->ncache, 0, NULL, + cmd_ctx->mapname); + if (req == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "cache_req_autofs_map_by_name_send failed\n"); + ret = ENOMEM; + goto done; + } +@@ -685,7 +685,7 @@ sss_autofs_cmd_getautomntent(struct cli_ctx *cli_ctx) + + req = autofs_setent_send(cli_ctx, cli_ctx->ev, autofs_ctx, cmd_ctx->mapname); + if (req == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "autofs_setent_send failed\n"); + ret = ENOMEM; + goto done; + } +@@ -886,7 +886,7 @@ sss_autofs_cmd_getautomntbyname(struct cli_ctx *cli_ctx) + cmd_ctx->mapname, + cmd_ctx->keyname); + if (req == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "cache_req_autofs_entry_by_name_send failed\n"); + ret = ENOMEM; + goto done; + } +diff --git a/src/responder/common/cache_req/cache_req.c b/src/responder/common/cache_req/cache_req.c +index 0c8538414..c6902f842 100644 +--- a/src/responder/common/cache_req/cache_req.c ++++ b/src/responder/common/cache_req/cache_req.c +@@ -1187,7 +1187,7 @@ static errno_t cache_req_process_input(TALLOC_CTX *mem_ctx, + subreq = sss_parse_inp_send(mem_ctx, cr->rctx, default_domain, + cr->data->name.input); + if (subreq == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "sss_parse_inp_send() failed\n"); + return ENOMEM; + } + +diff --git a/src/responder/common/cache_req/plugins/cache_req_object_by_name.c b/src/responder/common/cache_req/plugins/cache_req_object_by_name.c +index a740fbb8d..83d00f775 100644 +--- a/src/responder/common/cache_req/plugins/cache_req_object_by_name.c ++++ b/src/responder/common/cache_req/plugins/cache_req_object_by_name.c +@@ -47,8 +47,8 @@ cache_req_object_by_name_well_known(TALLOC_CTX *mem_ctx, + } + + if (domname == NULL || name == NULL) { +- CACHE_REQ_DEBUG(SSSDBG_OP_FAILURE, cr, "Unable to split [%s] in " +- "name and odmain part. Skipping detection of " ++ CACHE_REQ_DEBUG(SSSDBG_FUNC_DATA, cr, "Unable to split [%s] in " ++ "name and domain part. Skipping detection of " + "well-known name.\n", data->name.input); + return ENOENT; + } +diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c +index e8d298546..7061d018a 100644 +--- a/src/responder/common/responder_common.c ++++ b/src/responder/common/responder_common.c +@@ -116,7 +116,7 @@ static errno_t get_client_cred(struct cli_ctx *cctx) + if (ret != EOK) { + ret = errno; + DEBUG(SSSDBG_CRIT_FAILURE, +- "getsock failed [%d][%s].\n", ret, strerror(ret)); ++ "getsockopt failed [%d][%s].\n", ret, strerror(ret)); + return ret; + } + if (client_cred_len != sizeof(struct ucred)) { +@@ -805,7 +805,7 @@ sss_dp_on_reconnect(struct sbus_connection *conn, + SSS_BUS_PATH, + be_conn->cli_name); + if (req == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "sbus_call_dp_client_Register_send() failed\n"); + return; + } + +diff --git a/src/responder/common/responder_get_domains.c b/src/responder/common/responder_get_domains.c +index 10939600d..e551b0fff 100644 +--- a/src/responder/common/responder_get_domains.c ++++ b/src/responder/common/responder_get_domains.c +@@ -630,7 +630,7 @@ static void sss_parse_inp_done(struct tevent_req *subreq) + state->rawinp, + &state->domname, &state->name); + if (ret == EAGAIN && state->domname != NULL && state->name == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, ++ DEBUG(SSSDBG_FUNC_DATA, + "Unknown domain in [%s]\n", state->rawinp); + state->error = ERR_DOMAIN_NOT_FOUND; + } else if (ret != EOK) { +diff --git a/src/responder/common/responder_iface.c b/src/responder/common/responder_iface.c +index 911cd6cc0..aaa765950 100644 +--- a/src/responder/common/responder_iface.c ++++ b/src/responder/common/responder_iface.c +@@ -127,7 +127,7 @@ sss_resp_register_sbus_iface(struct sbus_connection *conn, + + ret = sbus_connection_add_path_map(conn, paths); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add paths [%d]: %s\n", ++ DEBUG(SSSDBG_FATAL_FAILURE, "Unable to add paths [%d]: %s\n", + ret, sss_strerror(ret)); + } + +@@ -151,7 +151,7 @@ sss_resp_register_service_iface(struct resp_ctx *rctx) + + ret = sbus_connection_add_path(rctx->mon_conn, SSS_BUS_PATH, &iface_svc); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to register service interface" ++ DEBUG(SSSDBG_FATAL_FAILURE, "Unable to register service interface" + "[%d]: %s\n", ret, sss_strerror(ret)); + } + +diff --git a/src/responder/ifp/ifp_iface/ifp_iface.c b/src/responder/ifp/ifp_iface/ifp_iface.c +index a3385091b..833cf6843 100644 +--- a/src/responder/ifp/ifp_iface/ifp_iface.c ++++ b/src/responder/ifp/ifp_iface/ifp_iface.c +@@ -264,7 +264,7 @@ ifp_register_sbus_interface(struct sbus_connection *conn, + + ret = sbus_connection_add_path_map(conn, paths); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add paths [%d]: %s\n", ++ DEBUG(SSSDBG_FATAL_FAILURE, "Unable to add paths [%d]: %s\n", + ret, sss_strerror(ret)); + } + +diff --git a/src/responder/ifp/ifpsrv.c b/src/responder/ifp/ifpsrv.c +index 17d7692d3..7407ee07b 100644 +--- a/src/responder/ifp/ifpsrv.c ++++ b/src/responder/ifp/ifpsrv.c +@@ -67,7 +67,7 @@ sysbus_init(TALLOC_CTX *mem_ctx, + sysbus = sbus_connect_system(mem_ctx, ev, dbus_name, + &ifp_ctx->rctx->last_request_time); + if (sysbus == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to connect to system bus!\n"); ++ DEBUG(SSSDBG_FATAL_FAILURE, "Unable to connect to system bus!\n"); + return ERR_NO_SYSBUS; + } + +@@ -75,13 +75,13 @@ sysbus_init(TALLOC_CTX *mem_ctx, + + ret = ifp_register_sbus_interface(sysbus, ifp_ctx); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Could not register interfaces\n"); ++ DEBUG(SSSDBG_FATAL_FAILURE, "Could not register interfaces\n"); + goto done; + } + + ret = ifp_register_nodes(ifp_ctx, sysbus); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Could not register nodes factories\n"); ++ DEBUG(SSSDBG_FATAL_FAILURE, "Could not register nodes factories\n"); + goto done; + } + +@@ -148,7 +148,7 @@ ifp_register_service_iface(struct ifp_ctx *ifp_ctx, + + ret = sbus_connection_add_path(rctx->mon_conn, SSS_BUS_PATH, &iface_svc); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to register service interface" ++ DEBUG(SSSDBG_FATAL_FAILURE, "Unable to register service interface" + "[%d]: %s\n", ret, sss_strerror(ret)); + } + +diff --git a/src/responder/ifp/ifpsrv_util.c b/src/responder/ifp/ifpsrv_util.c +index ebc4c2118..3b3df7bc0 100644 +--- a/src/responder/ifp/ifpsrv_util.c ++++ b/src/responder/ifp/ifpsrv_util.c +@@ -341,7 +341,7 @@ immediately: + list_ctx->paths = talloc_realloc(list_ctx, list_ctx->paths, const char *, + list_ctx->paths_max + 1); + if (list_ctx->paths == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero_array() failed\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_realloc() failed\n"); + ret = ENOMEM; + goto done; + } +diff --git a/src/responder/nss/nss_cmd.c b/src/responder/nss/nss_cmd.c +index eac955b4a..844776c5f 100644 +--- a/src/responder/nss/nss_cmd.c ++++ b/src/responder/nss/nss_cmd.c +@@ -121,7 +121,7 @@ static errno_t nss_getby_name(struct cli_ctx *cli_ctx, + subreq = nss_get_object_send(cmd_ctx, cli_ctx->ev, cli_ctx, + data, memcache, rawname, 0); + if (subreq == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "nss_get_object_send() failed\n"); + ret = ENOMEM; + goto done; + } +@@ -187,7 +187,7 @@ static errno_t nss_getby_id(struct cli_ctx *cli_ctx, + subreq = nss_get_object_send(cmd_ctx, cli_ctx->ev, cli_ctx, + data, memcache, NULL, id); + if (subreq == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "nss_get_object_send() failed\n"); + ret = ENOMEM; + goto done; + } +@@ -240,7 +240,7 @@ static errno_t nss_getby_svc(struct cli_ctx *cli_ctx, + subreq = nss_get_object_send(cmd_ctx, cli_ctx->ev, cli_ctx, + data, SSS_MC_NONE, NULL, 0); + if (subreq == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "nss_get_object_send() failed\n"); + return ENOMEM; + } + +@@ -376,7 +376,7 @@ static errno_t nss_getby_cert(struct cli_ctx *cli_ctx, + subreq = nss_get_object_send(cmd_ctx, cli_ctx->ev, cli_ctx, + data, SSS_MC_NONE, NULL, 0); + if (subreq == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "nss_get_object_send() failed\n"); + ret = ENOMEM; + goto done; + } +@@ -433,7 +433,7 @@ static errno_t nss_getby_sid(struct cli_ctx *cli_ctx, + subreq = nss_get_object_send(cmd_ctx, cli_ctx->ev, cli_ctx, + data, SSS_MC_NONE, NULL, 0); + if (subreq == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "nss_get_object_send() failed\n"); + ret = ENOMEM; + goto done; + } +@@ -488,7 +488,7 @@ static errno_t nss_getby_addr(struct cli_ctx *cli_ctx, + subreq = nss_get_object_send(cmd_ctx, cli_ctx->ev, cli_ctx, + data, memcache, NULL, 0); + if (subreq == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "nss_get_object_send() failed\n"); + ret = ENOMEM; + goto done; + } +@@ -640,7 +640,7 @@ static errno_t nss_setent(struct cli_ctx *cli_ctx, + + subreq = nss_setent_send(cli_ctx, cli_ctx->ev, cli_ctx, type, enum_ctx); + if (subreq == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "nss_setent_send() failed\n"); + return ENOMEM; + } + +@@ -697,7 +697,7 @@ static errno_t nss_getent(struct cli_ctx *cli_ctx, + + subreq = nss_setent_send(cli_ctx, cli_ctx->ev, cli_ctx, type, enum_ctx); + if (subreq == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create setent request!\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "nss_setent_send() failed\n"); + ret = ENOMEM; + goto done; + } +@@ -829,7 +829,7 @@ static errno_t sss_nss_setnetgrent(struct cli_ctx *cli_ctx, + subreq = nss_setnetgrent_send(cli_ctx, cli_ctx->ev, cli_ctx, type, + nss_ctx->netgrent, state_ctx->netgroup); + if (subreq == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "nss_setnetgrent_send() failed\n"); + ret = ENOMEM; + goto done; + } +@@ -904,7 +904,7 @@ static errno_t nss_getnetgrent(struct cli_ctx *cli_ctx, + cmd_ctx->nss_ctx->netgrent, + cmd_ctx->state_ctx->netgroup); + if (subreq == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "nss_setnetgrent_send() failed\n"); + return ENOMEM; + } + +diff --git a/src/responder/nss/nss_iface.c b/src/responder/nss/nss_iface.c +index a47b35fca..ab2ba926d 100644 +--- a/src/responder/nss/nss_iface.c ++++ b/src/responder/nss/nss_iface.c +@@ -67,7 +67,7 @@ nss_update_initgr_memcache(struct nss_ctx *nctx, + ret = sysdb_initgroups(tmp_ctx, dom, fq_name, &res); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_CRIT_FAILURE, +- "Failed to make request to our cache! [%d][%s]\n", ++ "sysdb_initgroups() failed [%d][%s]\n", + ret, strerror(ret)); + goto done; + } +@@ -234,7 +234,7 @@ nss_register_backend_iface(struct sbus_connection *conn, + + ret = sbus_connection_add_path(conn, SSS_BUS_PATH, &iface); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to register service interface" ++ DEBUG(SSSDBG_FATAL_FAILURE, "Unable to register service interface" + "[%d]: %s\n", ret, sss_strerror(ret)); + } + +diff --git a/src/responder/nss/nss_protocol_netgr.c b/src/responder/nss/nss_protocol_netgr.c +index 1e9959c72..274d43007 100644 +--- a/src/responder/nss/nss_protocol_netgr.c ++++ b/src/responder/nss/nss_protocol_netgr.c +@@ -159,7 +159,7 @@ nss_protocol_fill_netgrent(struct nss_ctx *nss_ctx, + ret = nss_protocol_fill_netgr_member(packet, entry, &rp); + break; + default: +- DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected value type!\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected value type %d!\n", entry->type); + ret = ERR_INTERNAL; + break; + } +diff --git a/src/responder/nss/nsssrv.c b/src/responder/nss/nsssrv.c +index 31a2750b1..e80104e3d 100644 +--- a/src/responder/nss/nsssrv.c ++++ b/src/responder/nss/nsssrv.c +@@ -347,7 +347,7 @@ nss_register_service_iface(struct nss_ctx *nss_ctx, + + ret = sbus_connection_add_path(rctx->mon_conn, SSS_BUS_PATH, &iface_svc); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to register service interface" ++ DEBUG(SSSDBG_FATAL_FAILURE, "Unable to register service interface" + "[%d]: %s\n", ret, sss_strerror(ret)); + } + +diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c +index d3f092b2b..c526f665b 100644 +--- a/src/responder/pam/pamsrv_cmd.c ++++ b/src/responder/pam/pamsrv_cmd.c +@@ -138,7 +138,7 @@ static void inform_user(struct pam_data* pd, const char *pam_message) + 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"); ++ "pack_user_info_msg failed.\n"); + } else { + ret = pam_add_response(pd, SSS_PAM_USER_INFO, msg_len, msg); + if (ret != EOK) { +diff --git a/src/responder/pam/pamsrv_p11.c b/src/responder/pam/pamsrv_p11.c +index e1fd72e64..bf285c264 100644 +--- a/src/responder/pam/pamsrv_p11.c ++++ b/src/responder/pam/pamsrv_p11.c +@@ -425,7 +425,7 @@ bool may_do_cert_auth(struct pam_ctx *pctx, struct pam_data *pd) + } + } + if (pctx->smartcard_services[c] == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, ++ DEBUG(SSSDBG_CONF_SETTINGS, + "Smartcard authentication for service [%s] not supported.\n", + pd->service); + return false; +@@ -810,7 +810,7 @@ struct tevent_req *pam_check_cert_send(TALLOC_CTX *mem_ctx, + } else if (pd->cmd == SSS_PAM_PREAUTH) { + extra_args[arg_c++] = "--pre"; + } else { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected PAM command [%d}.\n", pd->cmd); ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unexpected PAM command [%d].\n", pd->cmd); + ret = EINVAL; + goto done; + } +diff --git a/src/sbus/router/sbus_router_handler.c b/src/sbus/router/sbus_router_handler.c +index 91a84c51b..a92cf524b 100644 +--- a/src/sbus/router/sbus_router_handler.c ++++ b/src/sbus/router/sbus_router_handler.c +@@ -239,7 +239,8 @@ sbus_signal_handler(struct sbus_connection *conn, + list = sbus_router_listeners_lookup(router->listeners, meta->interface, + meta->member); + if (list == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "We do not listen to this signal!\n"); ++ /* Most probably not fully initialized yet */ ++ DEBUG(SSSDBG_FUNC_DATA, "We do not listen to this signal!\n"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } + +diff --git a/src/sss_iface/sss_iface.c b/src/sss_iface/sss_iface.c +index e20c14fea..ed70e30eb 100644 +--- a/src/sss_iface/sss_iface.c ++++ b/src/sss_iface/sss_iface.c +@@ -116,8 +116,8 @@ sss_iface_connect_address(TALLOC_CTX *mem_ctx, + + conn = sbus_connect_private(mem_ctx, ev, address, + conn_name, last_request_time); +- if (conn == NULL) { +- return ENOMEM; ++ if (conn == NULL) { /* most probably sbus_dbus_connect_address() failed */ ++ return EFAULT; + } + + *_conn = conn; +diff --git a/src/util/child_common.c b/src/util/child_common.c +index 5cac725ca..7e8c30552 100644 +--- a/src/util/child_common.c ++++ b/src/util/child_common.c +@@ -768,7 +768,7 @@ void exec_child_ex(TALLOC_CTX *mem_ctx, + binary, extra_argv, extra_args_only, + &argv); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "prepare_child_argv.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "prepare_child_argv() failed.\n"); + exit(EXIT_FAILURE); + } + +diff --git a/src/util/debug.h b/src/util/debug.h +index 20db0f5e4..43d36720f 100644 +--- a/src/util/debug.h ++++ b/src/util/debug.h +@@ -91,8 +91,8 @@ int get_fd_from_debug_file(void); + /* enables all debug levels; + 0x0800 isn't used for historical reasons: 0x1FFF0 - 0x0800 = 0x1F7F0 + */ +-#define SSSDBG_MASK_ALL 0x1F7F0 +-#define SSSDBG_DEFAULT SSSDBG_FATAL_FAILURE ++#define SSSDBG_MASK_ALL 0x1F7F0 ++#define SSSDBG_DEFAULT (SSSDBG_FATAL_FAILURE|SSSDBG_CRIT_FAILURE|SSSDBG_OP_FAILURE) + + #define SSSDBG_TIMESTAMP_UNRESOLVED -1 + #define SSSDBG_TIMESTAMP_DEFAULT 1 +diff --git a/src/util/domain_info_utils.c b/src/util/domain_info_utils.c +index 4d4726daa..57157861e 100644 +--- a/src/util/domain_info_utils.c ++++ b/src/util/domain_info_utils.c +@@ -207,7 +207,7 @@ find_domain_by_object_name_ex(struct sss_domain_info *domain, + ret = sss_parse_internal_fqname(tmp_ctx, object_name, + NULL, &domainname); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse name '%s' [%d]: %s\n", ++ DEBUG(SSSDBG_MINOR_FAILURE, "Unable to parse name '%s' [%d]: %s\n", + object_name, ret, sss_strerror(ret)); + goto done; + } +diff --git a/src/util/server.c b/src/util/server.c +index b27cbc155..869ed62a6 100644 +--- a/src/util/server.c ++++ b/src/util/server.c +@@ -374,7 +374,7 @@ static void te_server_hup(struct tevent_context *ev, + struct logrotate_ctx *lctx = + talloc_get_type(private_data, struct logrotate_ctx); + +- DEBUG(SSSDBG_CRIT_FAILURE, "Received SIGHUP. Rotating logfiles.\n"); ++ DEBUG(SSSDBG_IMPORTANT_INFO, "Received SIGHUP. Rotating logfiles.\n"); + + ret = server_common_rotate_logs(lctx->confdb, lctx->confdb_path); + if (ret != EOK) { +@@ -462,6 +462,7 @@ int server_setup(const char *name, int flags, + int watchdog_interval; + pid_t my_pid; + char *pidfile_name; ++ int cfg_debug_level = SSSDBG_INVALID; + + my_pid = getpid(); + ret = setpgid(my_pid, my_pid); +@@ -588,20 +589,20 @@ int server_setup(const char *name, int flags, + /* set debug level if any in conf_entry */ + ret = confdb_get_int(ctx->confdb_ctx, conf_entry, + CONFDB_SERVICE_DEBUG_LEVEL, +- SSSDBG_UNRESOLVED, +- &debug_level); ++ SSSDBG_INVALID, ++ &cfg_debug_level); + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, "Error reading from confdb (%d) " + "[%s]\n", ret, strerror(ret)); + return ret; + } + +- if (debug_level == SSSDBG_UNRESOLVED) { ++ if (cfg_debug_level == SSSDBG_INVALID) { + /* Check for the `debug` alias */ + ret = confdb_get_int(ctx->confdb_ctx, conf_entry, + CONFDB_SERVICE_DEBUG_LEVEL_ALIAS, + SSSDBG_DEFAULT, +- &debug_level); ++ &cfg_debug_level); + if (ret != EOK) { + DEBUG(SSSDBG_FATAL_FAILURE, "Error reading from confdb (%d) " + "[%s]\n", ret, strerror(ret)); +@@ -609,7 +610,7 @@ int server_setup(const char *name, int flags, + } + } + +- debug_level = debug_convert_old_level(debug_level); ++ debug_level = debug_convert_old_level(cfg_debug_level); + } + + /* same for debug timestamps */ +@@ -678,6 +679,8 @@ int server_setup(const char *name, int flags, + return ret; + } + } ++ DEBUG(SSSDBG_IMPORTANT_INFO, ++ "Starting with debug level = %#.4x\n", debug_level); + + /* Setup the internal watchdog */ + ret = confdb_get_int(ctx->confdb_ctx, conf_entry, +diff --git a/src/util/sss_sockets.c b/src/util/sss_sockets.c +index c6504ae13..8944e2c4e 100644 +--- a/src/util/sss_sockets.c ++++ b/src/util/sss_sockets.c +@@ -322,7 +322,7 @@ struct tevent_req *sssd_async_socket_init_send(TALLOC_CTX *mem_ctx, + + ret = set_fcntl_flags(state->sd, FD_CLOEXEC, O_NONBLOCK); + if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "settting fd flags failed.\n"); ++ DEBUG(SSSDBG_CRIT_FAILURE, "setting fd flags failed.\n"); + goto fail; + } + +diff --git a/src/util/string_utils.c b/src/util/string_utils.c +index 1215ec96a..f54395a59 100644 +--- a/src/util/string_utils.c ++++ b/src/util/string_utils.c +@@ -90,7 +90,7 @@ errno_t guid_blob_to_string_buf(const uint8_t *blob, char *str_buf, + int ret; + + if (blob == NULL || str_buf == NULL || buf_size < GUID_STR_BUF_SIZE) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Buffer too small.\n"); ++ DEBUG(SSSDBG_OP_FAILURE, "Buffer too small.\n"); + return EINVAL; + } + +diff --git a/src/util/util_errors.c b/src/util/util_errors.c +index 05a66d293..b5c7419a9 100644 +--- a/src/util/util_errors.c ++++ b/src/util/util_errors.c +@@ -165,6 +165,7 @@ errno_t sss_ldb_error_to_errno(int ldberr) + case LDB_ERR_OPERATIONS_ERROR: + return EIO; + case LDB_ERR_NO_SUCH_OBJECT: ++ case LDB_ERR_NO_SUCH_ATTRIBUTE: + return ENOENT; + case LDB_ERR_BUSY: + return EBUSY; +@@ -174,7 +175,7 @@ errno_t sss_ldb_error_to_errno(int ldberr) + case LDB_ERR_INVALID_ATTRIBUTE_SYNTAX: + return EINVAL; + default: +- DEBUG(SSSDBG_CRIT_FAILURE, ++ DEBUG(SSSDBG_MINOR_FAILURE, + "LDB returned unexpected error: [%i]\n", + ldberr); + return EFAULT; +-- +2.21.3 + diff --git a/SOURCES/0020-sss_format.h-include-config.h.patch b/SOURCES/0020-sss_format.h-include-config.h.patch new file mode 100644 index 0000000..e237096 --- /dev/null +++ b/SOURCES/0020-sss_format.h-include-config.h.patch @@ -0,0 +1,31 @@ +From 45f2eb57dc9068cba13099cab90f1be3f3455442 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Fri, 2 Oct 2020 14:04:24 +0200 +Subject: [PATCH 20/27] sss_format.h: include config.h + +config.h is required for the definitions to work correctly. Compilation +will fail if sss_format.h is included in a file that does not include +directly or indirectly config.h + +Reviewed-by: Robbie Harwood +Reviewed-by: Sumit Bose +--- + src/util/sss_format.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/util/sss_format.h b/src/util/sss_format.h +index 5cf080842..9a3041704 100644 +--- a/src/util/sss_format.h ++++ b/src/util/sss_format.h +@@ -27,6 +27,8 @@ + #ifndef __SSS_FORMAT_H__ + #define __SSS_FORMAT_H__ + ++#include "config.h" ++ + #include + + /* key_serial_t is defined in keyutils.h as typedef int32_t */ +-- +2.21.3 + diff --git a/SOURCES/0021-packet-add-sss_packet_set_body.patch b/SOURCES/0021-packet-add-sss_packet_set_body.patch new file mode 100644 index 0000000..5311316 --- /dev/null +++ b/SOURCES/0021-packet-add-sss_packet_set_body.patch @@ -0,0 +1,59 @@ +From 3b0e48c33c6b43688ff46fed576266cfe6362595 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Thu, 8 Oct 2020 13:25:17 +0200 +Subject: [PATCH 21/27] packet: add sss_packet_set_body + +Reviewed-by: Robbie Harwood +Reviewed-by: Sumit Bose +--- + src/responder/common/responder_packet.c | 19 +++++++++++++++++++ + src/responder/common/responder_packet.h | 5 +++++ + 2 files changed, 24 insertions(+) + +diff --git a/src/responder/common/responder_packet.c b/src/responder/common/responder_packet.c +index ab15b1dac..f56d92276 100644 +--- a/src/responder/common/responder_packet.c ++++ b/src/responder/common/responder_packet.c +@@ -302,6 +302,25 @@ void sss_packet_get_body(struct sss_packet *packet, uint8_t **body, size_t *blen + *blen = sss_packet_get_len(packet) - SSS_NSS_HEADER_SIZE; + } + ++errno_t sss_packet_set_body(struct sss_packet *packet, ++ uint8_t *body, ++ size_t blen) ++{ ++ uint8_t *pbody; ++ size_t plen; ++ errno_t ret; ++ ++ ret = sss_packet_grow(packet, blen); ++ if (ret != EOK) { ++ return ret; ++ } ++ ++ sss_packet_get_body(packet, &pbody, &plen); ++ memcpy(pbody, body, blen); ++ ++ return EOK; ++} ++ + void sss_packet_set_error(struct sss_packet *packet, int error) + { + SAFEALIGN_SETMEM_UINT32(packet->buffer + SSS_PACKET_ERR_OFFSET, error, +diff --git a/src/responder/common/responder_packet.h b/src/responder/common/responder_packet.h +index afceb4aae..509a22a9a 100644 +--- a/src/responder/common/responder_packet.h ++++ b/src/responder/common/responder_packet.h +@@ -42,4 +42,9 @@ uint32_t sss_packet_get_status(struct sss_packet *packet); + void sss_packet_get_body(struct sss_packet *packet, uint8_t **body, size_t *blen); + void sss_packet_set_error(struct sss_packet *packet, int error); + ++/* Grow packet and set its body. */ ++errno_t sss_packet_set_body(struct sss_packet *packet, ++ uint8_t *body, ++ size_t blen); ++ + #endif /* __SSSSRV_PACKET_H__ */ +-- +2.21.3 + diff --git a/SOURCES/0022-domain-store-hostname-and-keytab-path.patch b/SOURCES/0022-domain-store-hostname-and-keytab-path.patch new file mode 100644 index 0000000..27628e6 --- /dev/null +++ b/SOURCES/0022-domain-store-hostname-and-keytab-path.patch @@ -0,0 +1,119 @@ +From 6715b31f2e12c7f76cfb477551cee46e697c7d51 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Thu, 8 Oct 2020 13:25:58 +0200 +Subject: [PATCH 22/27] domain: store hostname and keytab path + +Reviewed-by: Robbie Harwood +Reviewed-by: Sumit Bose +--- + src/confdb/confdb.c | 45 +++++++++++++++++++++++++++++++++++++++ + src/confdb/confdb.h | 6 ++++++ + src/db/sysdb_subdomains.c | 12 +++++++++++ + 3 files changed, 63 insertions(+) + +diff --git a/src/confdb/confdb.c b/src/confdb/confdb.c +index d2fc018fd..f981ddf1e 100644 +--- a/src/confdb/confdb.c ++++ b/src/confdb/confdb.c +@@ -871,6 +871,35 @@ done: + return ret; + } + ++static char *confdb_get_domain_hostname(TALLOC_CTX *mem_ctx, ++ struct ldb_result *res, ++ const char *provider) ++{ ++ char sys[HOST_NAME_MAX + 1] = {'\0'}; ++ const char *opt = NULL; ++ int ret; ++ ++ if (strcasecmp(provider, "ad") == 0) { ++ opt = ldb_msg_find_attr_as_string(res->msgs[0], "ad_hostname", NULL); ++ } else if (strcasecmp(provider, "ipa") == 0) { ++ opt = ldb_msg_find_attr_as_string(res->msgs[0], "ipa_hostname", NULL); ++ } ++ ++ if (opt != NULL) { ++ return talloc_strdup(mem_ctx, opt); ++ } ++ ++ ret = gethostname(sys, sizeof(sys)); ++ if (ret != 0) { ++ ret = errno; ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get hostname [%d]: %s\n", ret, ++ sss_strerror(ret)); ++ return NULL; ++ } ++ ++ return talloc_strdup(mem_ctx, sys); ++} ++ + static int confdb_get_domain_internal(struct confdb_ctx *cdb, + TALLOC_CTX *mem_ctx, + const char *name, +@@ -1536,6 +1565,22 @@ static int confdb_get_domain_internal(struct confdb_ctx *cdb, + goto done; + } + ++ domain->hostname = confdb_get_domain_hostname(domain, res, domain->provider); ++ if (domain->hostname == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get domain hostname\n"); ++ goto done; ++ } ++ ++ domain->krb5_keytab = NULL; ++ tmp = ldb_msg_find_attr_as_string(res->msgs[0], "krb5_keytab", NULL); ++ if (tmp != NULL) { ++ domain->krb5_keytab = talloc_strdup(domain, tmp); ++ if (domain->krb5_keytab == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get domain keytab!\n"); ++ goto done; ++ } ++ } ++ + domain->has_views = false; + domain->view_name = NULL; + +diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h +index fd6d76cde..54e3f7380 100644 +--- a/src/confdb/confdb.h ++++ b/src/confdb/confdb.h +@@ -425,6 +425,12 @@ struct sss_domain_info { + /* Do not use the _output_fqnames property directly in new code, but rather + * use sss_domain_info_{get,set}_output_fqnames(). */ + bool output_fqnames; ++ ++ /* Hostname associated with this domain. */ ++ const char *hostname; ++ ++ /* Keytab used by this domain. */ ++ const char *krb5_keytab; + }; + + /** +diff --git a/src/db/sysdb_subdomains.c b/src/db/sysdb_subdomains.c +index d256817a6..5b42f9bdc 100644 +--- a/src/db/sysdb_subdomains.c ++++ b/src/db/sysdb_subdomains.c +@@ -125,6 +125,18 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx, + } + } + ++ dom->hostname = talloc_strdup(dom, parent->hostname); ++ if (dom->hostname == NULL && parent->hostname != NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "Failed to copy hostname.\n"); ++ goto fail; ++ } ++ ++ dom->krb5_keytab = talloc_strdup(dom, parent->krb5_keytab); ++ if (dom->krb5_keytab == NULL && parent->krb5_keytab != NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "Failed to copy krb5_keytab.\n"); ++ goto fail; ++ } ++ + dom->enumerate = enumerate; + dom->fqnames = true; + dom->mpg_mode = mpg_mode; +-- +2.21.3 + diff --git a/SOURCES/0023-cache_req-add-helper-to-call-user-by-upn-search.patch b/SOURCES/0023-cache_req-add-helper-to-call-user-by-upn-search.patch new file mode 100644 index 0000000..168f8b6 --- /dev/null +++ b/SOURCES/0023-cache_req-add-helper-to-call-user-by-upn-search.patch @@ -0,0 +1,70 @@ +From a3e2677f919c6b1b1649ad80cc3435b4bb2efc0d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Thu, 10 Dec 2020 19:28:58 +0100 +Subject: [PATCH 23/27] cache_req: add helper to call user by upn search + +Reviewed-by: Robbie Harwood +Reviewed-by: Sumit Bose +--- + src/responder/common/cache_req/cache_req.h | 13 +++++++++++ + .../cache_req/plugins/cache_req_user_by_upn.c | 23 +++++++++++++++++++ + 2 files changed, 36 insertions(+) + +diff --git a/src/responder/common/cache_req/cache_req.h b/src/responder/common/cache_req/cache_req.h +index d36cb2d3b..d301a076e 100644 +--- a/src/responder/common/cache_req/cache_req.h ++++ b/src/responder/common/cache_req/cache_req.h +@@ -277,6 +277,19 @@ cache_req_user_by_name_attrs_send(TALLOC_CTX *mem_ctx, + #define cache_req_user_by_name_attrs_recv(mem_ctx, req, _result) \ + cache_req_single_domain_recv(mem_ctx, req, _result) + ++struct tevent_req * ++cache_req_user_by_upn_send(TALLOC_CTX *mem_ctx, ++ struct tevent_context *ev, ++ struct resp_ctx *rctx, ++ struct sss_nc_ctx *ncache, ++ int cache_refresh_percent, ++ enum cache_req_dom_type req_dom_type, ++ const char *domain, ++ const char *upn); ++ ++#define cache_req_user_by_upn_recv(mem_ctx, req, _result) \ ++ cache_req_single_domain_recv(mem_ctx, req, _result); ++ + struct tevent_req * + cache_req_user_by_id_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, +diff --git a/src/responder/common/cache_req/plugins/cache_req_user_by_upn.c b/src/responder/common/cache_req/plugins/cache_req_user_by_upn.c +index e08ab70ae..037994c8c 100644 +--- a/src/responder/common/cache_req/plugins/cache_req_user_by_upn.c ++++ b/src/responder/common/cache_req/plugins/cache_req_user_by_upn.c +@@ -133,3 +133,26 @@ const struct cache_req_plugin cache_req_user_by_upn = { + .dp_get_domain_send_fn = NULL, + .dp_get_domain_recv_fn = NULL, + }; ++ ++struct tevent_req * ++cache_req_user_by_upn_send(TALLOC_CTX *mem_ctx, ++ struct tevent_context *ev, ++ struct resp_ctx *rctx, ++ struct sss_nc_ctx *ncache, ++ int cache_refresh_percent, ++ enum cache_req_dom_type req_dom_type, ++ const char *domain, ++ const char *upn) ++{ ++ struct cache_req_data *data; ++ ++ data = cache_req_data_name(mem_ctx, CACHE_REQ_USER_BY_UPN, upn); ++ if (data == NULL) { ++ return NULL; ++ } ++ ++ return cache_req_steal_data_and_send(mem_ctx, ev, rctx, ncache, ++ cache_refresh_percent, ++ req_dom_type, domain, ++ data); ++} +-- +2.21.3 + diff --git a/SOURCES/0024-pam-fix-typo-in-debug-message.patch b/SOURCES/0024-pam-fix-typo-in-debug-message.patch new file mode 100644 index 0000000..25167e1 --- /dev/null +++ b/SOURCES/0024-pam-fix-typo-in-debug-message.patch @@ -0,0 +1,27 @@ +From dcc42015f7ada1c4e4daed17e2c8087e29cb7616 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Thu, 1 Oct 2020 14:02:44 +0200 +Subject: [PATCH 24/27] pam: fix typo in debug message + +Reviewed-by: Robbie Harwood +Reviewed-by: Sumit Bose +--- + src/responder/pam/pamsrv_cmd.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c +index 1d0251497..acbfc0c39 100644 +--- a/src/responder/pam/pamsrv_cmd.c ++++ b/src/responder/pam/pamsrv_cmd.c +@@ -1941,7 +1941,7 @@ static void pam_check_user_search_next(struct tevent_req *req) + talloc_zfree(req); + if (ret != EOK && ret != ENOENT) { + DEBUG(SSSDBG_OP_FAILURE, "Cache lookup failed, trying to get fresh " +- "data from the backened.\n"); ++ "data from the backend.\n"); + } + + DEBUG(SSSDBG_TRACE_ALL, "PAM initgroups scheme [%s].\n", +-- +2.21.3 + diff --git a/SOURCES/0025-pam-add-pam_gssapi_services-option.patch b/SOURCES/0025-pam-add-pam_gssapi_services-option.patch new file mode 100644 index 0000000..7c90067 --- /dev/null +++ b/SOURCES/0025-pam-add-pam_gssapi_services-option.patch @@ -0,0 +1,280 @@ +From d63172f1277c5ed166a22f04d144bf85ded4757c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Fri, 9 Oct 2020 13:03:54 +0200 +Subject: [PATCH 25/27] pam: add pam_gssapi_services option + +:config: Added `pam_gssapi_services` to list PAM services + that can authenticate using GSSAPI + +Reviewed-by: Robbie Harwood +Reviewed-by: Sumit Bose +--- + src/confdb/confdb.c | 12 +++++++++++ + src/confdb/confdb.h | 4 ++++ + src/config/SSSDConfig/sssdoptions.py | 1 + + src/config/SSSDConfigTest.py | 6 ++++-- + src/config/cfg_rules.ini | 3 +++ + src/config/etc/sssd.api.conf | 2 ++ + src/db/sysdb_subdomains.c | 13 ++++++++++++ + src/man/sssd.conf.5.xml | 30 ++++++++++++++++++++++++++++ + src/responder/pam/pamsrv.c | 21 +++++++++++++++++++ + src/responder/pam/pamsrv.h | 3 +++ + 10 files changed, 93 insertions(+), 2 deletions(-) + +diff --git a/src/confdb/confdb.c b/src/confdb/confdb.c +index f981ddf1e..7f1956d6d 100644 +--- a/src/confdb/confdb.c ++++ b/src/confdb/confdb.c +@@ -1581,6 +1581,18 @@ static int confdb_get_domain_internal(struct confdb_ctx *cdb, + } + } + ++ tmp = ldb_msg_find_attr_as_string(res->msgs[0], CONFDB_PAM_GSSAPI_SERVICES, ++ "-"); ++ if (tmp != NULL) { ++ ret = split_on_separator(domain, tmp, ',', true, true, ++ &domain->gssapi_services, NULL); ++ if (ret != 0) { ++ DEBUG(SSSDBG_FATAL_FAILURE, ++ "Cannot parse %s\n", CONFDB_PAM_GSSAPI_SERVICES); ++ goto done; ++ } ++ } ++ + domain->has_views = false; + domain->view_name = NULL; + +diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h +index 54e3f7380..7a3bc8bb5 100644 +--- a/src/confdb/confdb.h ++++ b/src/confdb/confdb.h +@@ -144,6 +144,7 @@ + #define CONFDB_PAM_P11_ALLOWED_SERVICES "pam_p11_allowed_services" + #define CONFDB_PAM_P11_URI "p11_uri" + #define CONFDB_PAM_INITGROUPS_SCHEME "pam_initgroups_scheme" ++#define CONFDB_PAM_GSSAPI_SERVICES "pam_gssapi_services" + + /* SUDO */ + #define CONFDB_SUDO_CONF_ENTRY "config/sudo" +@@ -431,6 +432,9 @@ struct sss_domain_info { + + /* Keytab used by this domain. */ + const char *krb5_keytab; ++ ++ /* List of PAM services that are allowed to authenticate with GSSAPI. */ ++ char **gssapi_services; + }; + + /** +diff --git a/src/config/SSSDConfig/sssdoptions.py b/src/config/SSSDConfig/sssdoptions.py +index de96db6f4..f59fe8d9f 100644 +--- a/src/config/SSSDConfig/sssdoptions.py ++++ b/src/config/SSSDConfig/sssdoptions.py +@@ -104,6 +104,7 @@ class SSSDOptions(object): + 'p11_wait_for_card_timeout': _('Additional timeout to wait for a card if requested'), + 'p11_uri': _('PKCS#11 URI to restrict the selection of devices for Smartcard authentication'), + 'pam_initgroups_scheme' : _('When shall the PAM responder force an initgroups request'), ++ 'pam_gssapi_services' : _('List of PAM services that are allowed to authenticate with GSSAPI.'), + + # [sudo] + 'sudo_timed': _('Whether to evaluate the time-based attributes in sudo rules'), +diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py +index 323be5ed3..21fffe1b6 100755 +--- a/src/config/SSSDConfigTest.py ++++ b/src/config/SSSDConfigTest.py +@@ -653,7 +653,8 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase): + 'full_name_format', + 're_expression', + 'cached_auth_timeout', +- 'auto_private_groups'] ++ 'auto_private_groups', ++ 'pam_gssapi_services'] + + self.assertTrue(type(options) == dict, + "Options should be a dictionary") +@@ -1030,7 +1031,8 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase): + 'full_name_format', + 're_expression', + 'cached_auth_timeout', +- 'auto_private_groups'] ++ 'auto_private_groups', ++ 'pam_gssapi_services'] + + self.assertTrue(type(options) == dict, + "Options should be a dictionary") +diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini +index 773afd8bb..c6dfd5648 100644 +--- a/src/config/cfg_rules.ini ++++ b/src/config/cfg_rules.ini +@@ -139,6 +139,7 @@ option = pam_p11_allowed_services + option = p11_wait_for_card_timeout + option = p11_uri + option = pam_initgroups_scheme ++option = pam_gssapi_services + + [rule/allowed_sudo_options] + validator = ini_allowed_options +@@ -437,6 +438,7 @@ option = wildcard_limit + option = full_name_format + option = re_expression + option = auto_private_groups ++option = pam_gssapi_services + + #Entry cache timeouts + option = entry_cache_user_timeout +@@ -831,6 +833,7 @@ option = ad_backup_server + option = ad_site + option = use_fully_qualified_names + option = auto_private_groups ++option = pam_gssapi_services + + [rule/sssd_checks] + validator = sssd_checks +diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf +index 623160ffd..f46f3c46d 100644 +--- a/src/config/etc/sssd.api.conf ++++ b/src/config/etc/sssd.api.conf +@@ -80,6 +80,7 @@ pam_p11_allowed_services = str, None, false + p11_wait_for_card_timeout = int, None, false + p11_uri = str, None, false + pam_initgroups_scheme = str, None, false ++pam_gssapi_services = str, None, false + + [sudo] + # sudo service +@@ -199,6 +200,7 @@ cached_auth_timeout = int, None, false + full_name_format = str, None, false + re_expression = str, None, false + auto_private_groups = str, None, false ++pam_gssapi_services = str, None, false + + #Entry cache timeouts + entry_cache_user_timeout = int, None, false +diff --git a/src/db/sysdb_subdomains.c b/src/db/sysdb_subdomains.c +index 5b42f9bdc..bfc6df0f5 100644 +--- a/src/db/sysdb_subdomains.c ++++ b/src/db/sysdb_subdomains.c +@@ -184,6 +184,8 @@ struct sss_domain_info *new_subdomain(TALLOC_CTX *mem_ctx, + dom->homedir_substr = parent->homedir_substr; + dom->override_gid = parent->override_gid; + ++ dom->gssapi_services = parent->gssapi_services; ++ + if (parent->sysdb == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "Missing sysdb context in parent domain.\n"); + goto fail; +@@ -241,6 +243,17 @@ check_subdom_config_file(struct confdb_ctx *confdb, + sd_conf_path, CONFDB_DOMAIN_FQ, + subdomain->fqnames ? "TRUE" : "FALSE"); + ++ /* allow to set pam_gssapi_services */ ++ ret = confdb_get_string_as_list(confdb, subdomain, sd_conf_path, ++ CONFDB_PAM_GSSAPI_SERVICES, ++ &subdomain->gssapi_services); ++ if (ret != EOK && ret != ENOENT) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "Failed to get %s option for the subdomain: %s\n", ++ CONFDB_PAM_GSSAPI_SERVICES, subdomain->name); ++ goto done; ++ } ++ + ret = EOK; + done: + talloc_free(tmp_ctx); +diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml +index d247400bf..db9dd4677 100644 +--- a/src/man/sssd.conf.5.xml ++++ b/src/man/sssd.conf.5.xml +@@ -1706,6 +1706,35 @@ p11_uri = library-description=OpenSC%20smartcard%20framework;slot-id=2 + + + ++ ++ pam_gssapi_services ++ ++ ++ Comma separated list of PAM services that are ++ allowed to try GSSAPI authentication using ++ pam_sss_gss.so module. ++ ++ ++ To disable GSSAPI authentication, set this option ++ to - (dash). ++ ++ ++ Note: This option can also be set per-domain which ++ overwrites the value in [pam] section. It can also ++ be set for trusted domain which overwrites the value ++ in the domain section. ++ ++ ++ Example: ++ ++pam_gssapi_services = sudo, sudo-i ++ ++ ++ ++ Default: - (GSSAPI authentication is disabled) ++ ++ ++ + + + +@@ -3780,6 +3809,7 @@ ldap_user_extra_attrs = phone:telephoneNumber + ad_backup_server, + ad_site, + use_fully_qualified_names ++ pam_gssapi_services + + For more details about these options see their individual description + in the manual page. +diff --git a/src/responder/pam/pamsrv.c b/src/responder/pam/pamsrv.c +index 1f1ee608b..0492569c7 100644 +--- a/src/responder/pam/pamsrv.c ++++ b/src/responder/pam/pamsrv.c +@@ -327,6 +327,27 @@ static int pam_process_init(TALLOC_CTX *mem_ctx, + } + } + ++ ret = confdb_get_string(pctx->rctx->cdb, pctx, CONFDB_PAM_CONF_ENTRY, ++ CONFDB_PAM_GSSAPI_SERVICES, "-", &tmpstr); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_FATAL_FAILURE, ++ "Failed to determine gssapi services.\n"); ++ goto done; ++ } ++ DEBUG(SSSDBG_TRACE_INTERNAL, "Found value [%s] for option [%s].\n", tmpstr, ++ CONFDB_PAM_GSSAPI_SERVICES); ++ ++ if (tmpstr != NULL) { ++ ret = split_on_separator(pctx, tmpstr, ',', true, true, ++ &pctx->gssapi_services, NULL); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_MINOR_FAILURE, ++ "split_on_separator() failed [%d]: [%s].\n", ret, ++ sss_strerror(ret)); ++ goto done; ++ } ++ } ++ + /* The responder is initialized. Now tell it to the monitor. */ + ret = sss_monitor_service_init(rctx, rctx->ev, SSS_BUS_PAM, + SSS_PAM_SBUS_SERVICE_NAME, +diff --git a/src/responder/pam/pamsrv.h b/src/responder/pam/pamsrv.h +index 24d307a14..730dee288 100644 +--- a/src/responder/pam/pamsrv.h ++++ b/src/responder/pam/pamsrv.h +@@ -62,6 +62,9 @@ struct pam_ctx { + int num_prompting_config_sections; + + enum pam_initgroups_scheme initgroups_scheme; ++ ++ /* List of PAM services that are allowed to authenticate with GSSAPI. */ ++ char **gssapi_services; + }; + + struct pam_auth_req { +-- +2.21.3 + diff --git a/SOURCES/0026-pam-add-pam_gssapi_check_upn-option.patch b/SOURCES/0026-pam-add-pam_gssapi_check_upn-option.patch new file mode 100644 index 0000000..6e59705 --- /dev/null +++ b/SOURCES/0026-pam-add-pam_gssapi_check_upn-option.patch @@ -0,0 +1,250 @@ +From fffe3169bb490c4b010b168c639aa6f9b2ec0c52 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Thu, 10 Dec 2020 22:05:30 +0100 +Subject: [PATCH 26/27] pam: add pam_gssapi_check_upn option + +:config: Added `pam_gssapi_check_upn` to enforce authentication + only with principal that can be associated with target user. + +Reviewed-by: Robbie Harwood +Reviewed-by: Sumit Bose +--- + src/confdb/confdb.c | 10 ++++++++++ + src/confdb/confdb.h | 2 ++ + src/config/SSSDConfig/sssdoptions.py | 1 + + src/config/SSSDConfigTest.py | 6 ++++-- + src/config/cfg_rules.ini | 3 +++ + src/config/etc/sssd.api.conf | 2 ++ + src/db/sysdb_subdomains.c | 12 ++++++++++++ + src/man/sssd.conf.5.xml | 26 ++++++++++++++++++++++++++ + src/responder/pam/pamsrv.c | 9 +++++++++ + src/responder/pam/pamsrv.h | 1 + + 10 files changed, 70 insertions(+), 2 deletions(-) + +diff --git a/src/confdb/confdb.c b/src/confdb/confdb.c +index 7f1956d6d..2881ce5da 100644 +--- a/src/confdb/confdb.c ++++ b/src/confdb/confdb.c +@@ -1593,6 +1593,16 @@ static int confdb_get_domain_internal(struct confdb_ctx *cdb, + } + } + ++ tmp = ldb_msg_find_attr_as_string(res->msgs[0], CONFDB_PAM_GSSAPI_CHECK_UPN, ++ NULL); ++ if (tmp != NULL) { ++ domain->gssapi_check_upn = talloc_strdup(domain, tmp); ++ if (domain->gssapi_check_upn == NULL) { ++ ret = ENOMEM; ++ goto done; ++ } ++ } ++ + domain->has_views = false; + domain->view_name = NULL; + +diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h +index 7a3bc8bb5..036f9ecad 100644 +--- a/src/confdb/confdb.h ++++ b/src/confdb/confdb.h +@@ -145,6 +145,7 @@ + #define CONFDB_PAM_P11_URI "p11_uri" + #define CONFDB_PAM_INITGROUPS_SCHEME "pam_initgroups_scheme" + #define CONFDB_PAM_GSSAPI_SERVICES "pam_gssapi_services" ++#define CONFDB_PAM_GSSAPI_CHECK_UPN "pam_gssapi_check_upn" + + /* SUDO */ + #define CONFDB_SUDO_CONF_ENTRY "config/sudo" +@@ -435,6 +436,7 @@ struct sss_domain_info { + + /* List of PAM services that are allowed to authenticate with GSSAPI. */ + char **gssapi_services; ++ char *gssapi_check_upn; /* true | false | NULL */ + }; + + /** +diff --git a/src/config/SSSDConfig/sssdoptions.py b/src/config/SSSDConfig/sssdoptions.py +index f59fe8d9f..5da52a937 100644 +--- a/src/config/SSSDConfig/sssdoptions.py ++++ b/src/config/SSSDConfig/sssdoptions.py +@@ -105,6 +105,7 @@ class SSSDOptions(object): + 'p11_uri': _('PKCS#11 URI to restrict the selection of devices for Smartcard authentication'), + 'pam_initgroups_scheme' : _('When shall the PAM responder force an initgroups request'), + 'pam_gssapi_services' : _('List of PAM services that are allowed to authenticate with GSSAPI.'), ++ 'pam_gssapi_check_upn' : _('Whether to match authenticated UPN with target user'), + + # [sudo] + 'sudo_timed': _('Whether to evaluate the time-based attributes in sudo rules'), +diff --git a/src/config/SSSDConfigTest.py b/src/config/SSSDConfigTest.py +index 21fffe1b6..ea4e4f6c9 100755 +--- a/src/config/SSSDConfigTest.py ++++ b/src/config/SSSDConfigTest.py +@@ -654,7 +654,8 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase): + 're_expression', + 'cached_auth_timeout', + 'auto_private_groups', +- 'pam_gssapi_services'] ++ 'pam_gssapi_services', ++ 'pam_gssapi_check_upn'] + + self.assertTrue(type(options) == dict, + "Options should be a dictionary") +@@ -1032,7 +1033,8 @@ class SSSDConfigTestSSSDDomain(unittest.TestCase): + 're_expression', + 'cached_auth_timeout', + 'auto_private_groups', +- 'pam_gssapi_services'] ++ 'pam_gssapi_services', ++ 'pam_gssapi_check_upn'] + + self.assertTrue(type(options) == dict, + "Options should be a dictionary") +diff --git a/src/config/cfg_rules.ini b/src/config/cfg_rules.ini +index c6dfd5648..6642c6321 100644 +--- a/src/config/cfg_rules.ini ++++ b/src/config/cfg_rules.ini +@@ -140,6 +140,7 @@ option = p11_wait_for_card_timeout + option = p11_uri + option = pam_initgroups_scheme + option = pam_gssapi_services ++option = pam_gssapi_check_upn + + [rule/allowed_sudo_options] + validator = ini_allowed_options +@@ -439,6 +440,7 @@ option = full_name_format + option = re_expression + option = auto_private_groups + option = pam_gssapi_services ++option = pam_gssapi_check_upn + + #Entry cache timeouts + option = entry_cache_user_timeout +@@ -834,6 +836,7 @@ option = ad_site + option = use_fully_qualified_names + option = auto_private_groups + option = pam_gssapi_services ++option = pam_gssapi_check_upn + + [rule/sssd_checks] + validator = sssd_checks +diff --git a/src/config/etc/sssd.api.conf b/src/config/etc/sssd.api.conf +index f46f3c46d..d3cad7380 100644 +--- a/src/config/etc/sssd.api.conf ++++ b/src/config/etc/sssd.api.conf +@@ -81,6 +81,7 @@ p11_wait_for_card_timeout = int, None, false + p11_uri = str, None, false + pam_initgroups_scheme = str, None, false + pam_gssapi_services = str, None, false ++pam_gssapi_check_upn = bool, None, false + + [sudo] + # sudo service +@@ -201,6 +202,7 @@ full_name_format = str, None, false + re_expression = str, None, false + auto_private_groups = str, None, false + pam_gssapi_services = str, None, false ++pam_gssapi_check_upn = bool, None, false + + #Entry cache timeouts + entry_cache_user_timeout = int, None, false +diff --git a/src/db/sysdb_subdomains.c b/src/db/sysdb_subdomains.c +index bfc6df0f5..03ba12164 100644 +--- a/src/db/sysdb_subdomains.c ++++ b/src/db/sysdb_subdomains.c +@@ -254,6 +254,18 @@ check_subdom_config_file(struct confdb_ctx *confdb, + goto done; + } + ++ /* allow to set pam_gssapi_check_upn */ ++ ret = confdb_get_string(confdb, subdomain, sd_conf_path, ++ CONFDB_PAM_GSSAPI_CHECK_UPN, ++ subdomain->parent->gssapi_check_upn, ++ &subdomain->gssapi_check_upn); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "Failed to get %s option for the subdomain: %s\n", ++ CONFDB_PAM_GSSAPI_CHECK_UPN, subdomain->name); ++ goto done; ++ } ++ + ret = EOK; + done: + talloc_free(tmp_ctx); +diff --git a/src/man/sssd.conf.5.xml b/src/man/sssd.conf.5.xml +index db9dd4677..d637e2eaa 100644 +--- a/src/man/sssd.conf.5.xml ++++ b/src/man/sssd.conf.5.xml +@@ -1735,6 +1735,31 @@ pam_gssapi_services = sudo, sudo-i + + + ++ ++ pam_gssapi_check_upn ++ ++ ++ If True, SSSD will require that the Kerberos user ++ principal that successfully authenticated through ++ GSSAPI can be associated with the user who is being ++ authenticated. Authentication will fail if the check ++ fails. ++ ++ ++ If False, every user that is able to obtained ++ required service ticket will be authenticated. ++ ++ ++ Note: This option can also be set per-domain which ++ overwrites the value in [pam] section. It can also ++ be set for trusted domain which overwrites the value ++ in the domain section. ++ ++ ++ Default: True ++ ++ ++ + + + +@@ -3810,6 +3835,7 @@ ldap_user_extra_attrs = phone:telephoneNumber + ad_site, + use_fully_qualified_names + pam_gssapi_services ++ pam_gssapi_check_upn + + For more details about these options see their individual description + in the manual page. +diff --git a/src/responder/pam/pamsrv.c b/src/responder/pam/pamsrv.c +index 0492569c7..0db2824ff 100644 +--- a/src/responder/pam/pamsrv.c ++++ b/src/responder/pam/pamsrv.c +@@ -348,6 +348,15 @@ static int pam_process_init(TALLOC_CTX *mem_ctx, + } + } + ++ ret = confdb_get_bool(pctx->rctx->cdb, CONFDB_PAM_CONF_ENTRY, ++ CONFDB_PAM_GSSAPI_CHECK_UPN, true, ++ &pctx->gssapi_check_upn); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_FATAL_FAILURE, "Failed to read %s [%d]: %s\n", ++ CONFDB_PAM_GSSAPI_CHECK_UPN, ret, sss_strerror(ret)); ++ goto done; ++ } ++ + /* The responder is initialized. Now tell it to the monitor. */ + ret = sss_monitor_service_init(rctx, rctx->ev, SSS_BUS_PAM, + SSS_PAM_SBUS_SERVICE_NAME, +diff --git a/src/responder/pam/pamsrv.h b/src/responder/pam/pamsrv.h +index 730dee288..bf4dd75b0 100644 +--- a/src/responder/pam/pamsrv.h ++++ b/src/responder/pam/pamsrv.h +@@ -65,6 +65,7 @@ struct pam_ctx { + + /* List of PAM services that are allowed to authenticate with GSSAPI. */ + char **gssapi_services; ++ bool gssapi_check_upn; + }; + + struct pam_auth_req { +-- +2.21.3 + diff --git a/SOURCES/0027-pam-add-pam_sss_gss-module-for-gssapi-authentication.patch b/SOURCES/0027-pam-add-pam_sss_gss-module-for-gssapi-authentication.patch new file mode 100644 index 0000000..baa7927 --- /dev/null +++ b/SOURCES/0027-pam-add-pam_sss_gss-module-for-gssapi-authentication.patch @@ -0,0 +1,1866 @@ +From d09aa174b04a825979f31c61b05239de088a732f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pavel=20B=C5=99ezina?= +Date: Tue, 7 Jul 2020 11:05:37 +0200 +Subject: [PATCH 27/27] pam: add pam_sss_gss module for gssapi authentication + +:feature: New PAM module `pam_sss_gss` for authentication using GSSAPI +:packaging: Added `pam_sss_gss.so` PAM module and `pam_sss_gss.8` manual page + +Reviewed-by: Robbie Harwood +Reviewed-by: Sumit Bose +--- + Makefile.am | 33 +- + configure.ac | 1 + + contrib/sssd.spec.in | 2 + + src/external/libgssapi_krb5.m4 | 8 + + src/man/Makefile.am | 4 +- + src/man/pam_sss_gss.8.xml | 209 ++++++++ + src/responder/pam/pamsrv.h | 4 + + src/responder/pam/pamsrv_cmd.c | 2 + + src/responder/pam/pamsrv_gssapi.c | 792 +++++++++++++++++++++++++++++ + src/sss_client/pam_sss_gss.c | 588 +++++++++++++++++++++ + src/sss_client/pam_sss_gss.exports | 4 + + src/sss_client/sss_cli.h | 8 + + src/tests/dlopen-tests.c | 1 + + 13 files changed, 1653 insertions(+), 3 deletions(-) + create mode 100644 src/external/libgssapi_krb5.m4 + create mode 100644 src/man/pam_sss_gss.8.xml + create mode 100644 src/responder/pam/pamsrv_gssapi.c + create mode 100644 src/sss_client/pam_sss_gss.c + create mode 100644 src/sss_client/pam_sss_gss.exports + +diff --git a/Makefile.am b/Makefile.am +index 430b4e842..1c82776ab 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -1585,12 +1585,14 @@ sssd_pam_SOURCES = \ + src/responder/pam/pamsrv_cmd.c \ + src/responder/pam/pamsrv_p11.c \ + src/responder/pam/pamsrv_dp.c \ ++ src/responder/pam/pamsrv_gssapi.c \ + src/responder/pam/pam_prompting_config.c \ + src/sss_client/pam_sss_prompt_config.c \ + src/responder/pam/pam_helpers.c \ + $(SSSD_RESPONDER_OBJ) + sssd_pam_CFLAGS = \ + $(AM_CFLAGS) \ ++ $(GSSAPI_KRB5_CFLAGS) \ + $(NULL) + sssd_pam_LDADD = \ + $(LIBADD_DL) \ +@@ -1599,6 +1601,7 @@ sssd_pam_LDADD = \ + $(SELINUX_LIBS) \ + $(PAM_LIBS) \ + $(SYSTEMD_DAEMON_LIBS) \ ++ $(GSSAPI_KRB5_LIBS) \ + libsss_certmap.la \ + $(SSSD_INTERNAL_LTLIBS) \ + libsss_iface.la \ +@@ -2710,6 +2713,7 @@ pam_srv_tests_SOURCES = \ + src/sss_client/pam_message.c \ + src/responder/pam/pamsrv_cmd.c \ + src/responder/pam/pamsrv_p11.c \ ++ src/responder/pam/pamsrv_gssapi.c \ + src/responder/pam/pam_helpers.c \ + src/responder/pam/pamsrv_dp.c \ + src/responder/pam/pam_LOCAL_domain.c \ +@@ -2721,6 +2725,7 @@ pam_srv_tests_CFLAGS = \ + -I$(abs_builddir)/src \ + $(AM_CFLAGS) \ + $(CMOCKA_CFLAGS) \ ++ $(GSSAPI_KRB5_CFLAGS) \ + $(NULL) + pam_srv_tests_LDFLAGS = \ + -Wl,-wrap,sss_packet_get_body \ +@@ -2736,6 +2741,7 @@ pam_srv_tests_LDADD = \ + $(SSSD_LIBS) \ + $(SSSD_INTERNAL_LTLIBS) \ + $(SYSTEMD_DAEMON_LIBS) \ ++ $(GSSAPI_KRB5_LIBS) \ + libsss_test_common.la \ + libsss_idmap.la \ + libsss_certmap.la \ +@@ -4149,6 +4155,28 @@ pam_sss_la_LDFLAGS = \ + -avoid-version \ + -Wl,--version-script,$(srcdir)/src/sss_client/sss_pam.exports + ++pamlib_LTLIBRARIES += pam_sss_gss.la ++pam_sss_gss_la_SOURCES = \ ++ src/sss_client/pam_sss_gss.c \ ++ src/sss_client/common.c \ ++ $(NULL) ++ ++pam_sss_gss_la_CFLAGS = \ ++ $(AM_CFLAGS) \ ++ $(GSSAPI_KRB5_CFLAGS) \ ++ $(NULL) ++ ++pam_sss_gss_la_LIBADD = \ ++ $(CLIENT_LIBS) \ ++ $(PAM_LIBS) \ ++ $(GSSAPI_KRB5_LIBS) \ ++ $(NULL) ++ ++pam_sss_gss_la_LDFLAGS = \ ++ -module \ ++ -avoid-version \ ++ -Wl,--version-script,$(srcdir)/src/sss_client/pam_sss_gss.exports ++ + if BUILD_SUDO + + libsss_sudo_la_SOURCES = \ +@@ -4187,7 +4215,10 @@ endif + + dist_noinst_DATA += \ + src/sss_client/sss_nss.exports \ +- src/sss_client/sss_pam.exports ++ src/sss_client/sss_pam.exports \ ++ src/sss_client/pam_sss_gss.exports \ ++ $(NULL) ++ + if BUILD_SUDO + dist_noinst_DATA += src/sss_client/sss_sudo.exports + endif +diff --git a/configure.ac b/configure.ac +index 0d24c4b35..75dc81d53 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -182,6 +182,7 @@ m4_include([src/external/libldb.m4]) + m4_include([src/external/libdhash.m4]) + m4_include([src/external/libcollection.m4]) + m4_include([src/external/libini_config.m4]) ++m4_include([src/external/libgssapi_krb5.m4]) + m4_include([src/external/pam.m4]) + m4_include([src/external/ldap.m4]) + m4_include([src/external/libpcre.m4]) +diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in +index ed81da535..f7e5ce133 100644 +--- a/contrib/sssd.spec.in ++++ b/contrib/sssd.spec.in +@@ -1166,6 +1166,7 @@ done + %license src/sss_client/COPYING src/sss_client/COPYING.LESSER + /%{_lib}/libnss_sss.so.2 + /%{_lib}/security/pam_sss.so ++/%{_lib}/security/pam_sss_gss.so + %{_libdir}/krb5/plugins/libkrb5/sssd_krb5_locator_plugin.so + %{_libdir}/krb5/plugins/authdata/sssd_pac_plugin.so + %if (0%{?with_cifs_utils_plugin} == 1) +@@ -1178,6 +1179,7 @@ done + %dir %{_libdir}/%{name}/modules + %{_libdir}/%{name}/modules/sssd_krb5_localauth_plugin.so + %{_mandir}/man8/pam_sss.8* ++%{_mandir}/man8/pam_sss_gss.8* + %{_mandir}/man8/sssd_krb5_locator_plugin.8* + + %files -n libsss_sudo +diff --git a/src/external/libgssapi_krb5.m4 b/src/external/libgssapi_krb5.m4 +new file mode 100644 +index 000000000..67f3c464d +--- /dev/null ++++ b/src/external/libgssapi_krb5.m4 +@@ -0,0 +1,8 @@ ++AC_SUBST(GSSAPI_KRB5_CFLAGS) ++AC_SUBST(GSSAPI_KRB5_LIBS) ++ ++PKG_CHECK_MODULES(GSSAPI_KRB5, ++ krb5-gssapi, ++ , ++ AC_MSG_ERROR("Please install krb5-devel") ++ ) +diff --git a/src/man/Makefile.am b/src/man/Makefile.am +index 351ab8015..c6890a792 100644 +--- a/src/man/Makefile.am ++++ b/src/man/Makefile.am +@@ -69,8 +69,8 @@ man_MANS = \ + sssd.8 sssd.conf.5 sssd-ldap.5 sssd-ldap-attributes.5 \ + sssd-krb5.5 sssd-simple.5 sss-certmap.5 \ + sssd_krb5_locator_plugin.8 \ +- pam_sss.8 sss_obfuscate.8 sss_cache.8 sss_debuglevel.8 sss_seed.8 \ +- sss_override.8 idmap_sss.8 sssctl.8 sssd-session-recording.5 \ ++ pam_sss.8 pam_sss_gss.8 sss_obfuscate.8 sss_cache.8 sss_debuglevel.8 \ ++ sss_seed.8 sss_override.8 idmap_sss.8 sssctl.8 sssd-session-recording.5 \ + $(NULL) + + if BUILD_LOCAL_PROVIDER +diff --git a/src/man/pam_sss_gss.8.xml b/src/man/pam_sss_gss.8.xml +new file mode 100644 +index 000000000..ce5b11bff +--- /dev/null ++++ b/src/man/pam_sss_gss.8.xml +@@ -0,0 +1,209 @@ ++ ++ ++ ++SSSD Manual pages ++ ++ ++ ++ ++ pam_sss_gss ++ 8 ++ ++ ++ ++ pam_sss_gss ++ PAM module for SSSD GSSAPI authentication ++ ++ ++ ++ ++ pam_sss_gss.so ++ ++ debug ++ ++ ++ ++ ++ ++ DESCRIPTION ++ ++ pam_sss_gss.so authenticates user ++ over GSSAPI in cooperation with SSSD. ++ ++ ++ This module will try to authenticate the user using the GSSAPI ++ hostbased service name host@hostname which translates to ++ host/hostname@REALM Kerberos principal. The ++ REALM part of the Kerberos principal name is ++ derived by Kerberos internal mechanisms and it can be set explicitly ++ in configuration of [domain_realm] section in /etc/krb5.conf. ++ ++ ++ SSSD is used to provide desired service name and to validate the ++ user's credentials using GSSAPI calls. If the service ticket is ++ already present in the Kerberos credentials cache or if user's ++ ticket granting ticket can be used to get the correct service ticket ++ then the user will be authenticated. ++ ++ ++ If is True (default) then SSSD ++ requires that the credentials used to obtain the service tickets can ++ be associated with the user. This means that the principal that owns ++ the Kerberos credentials must match with the user principal name as ++ defined in LDAP. ++ ++ ++ To enable GSSAPI authentication in SSSD, set ++ option in [pam] or domain ++ section of sssd.conf. The service credentials need to be stored ++ in SSSD's keytab (it is already present if you use ipa or ad ++ provider). The keytab location can be set with ++ option. See ++ ++ sssd.conf ++ 5 ++ and ++ ++ sssd-krb5 ++ 5 ++ for more details on these options. ++ ++ ++ ++ ++ OPTIONS ++ ++ ++ ++ ++ ++ ++ Print debugging information. ++ ++ ++ ++ ++ ++ ++ MODULE TYPES PROVIDED ++ Only the module type is provided. ++ ++ ++ ++ RETURN VALUES ++ ++ ++ PAM_SUCCESS ++ ++ ++ The PAM operation finished successfully. ++ ++ ++ ++ ++ PAM_USER_UNKNOWN ++ ++ ++ The user is not known to the authentication service or ++ the GSSAPI authentication is not supported. ++ ++ ++ ++ ++ PAM_AUTH_ERR ++ ++ ++ Authentication failure. ++ ++ ++ ++ ++ PAM_AUTHINFO_UNAVAIL ++ ++ ++ Unable to access the authentication information. ++ This might be due to a network or hardware failure. ++ ++ ++ ++ ++ PAM_SYSTEM_ERR ++ ++ ++ A system error occurred. The SSSD log files may contain ++ additional information about the error. ++ ++ ++ ++ ++ ++ ++ ++ EXAMPLES ++ ++ The main use case is to provide password-less authentication in ++ sudo but without the need to disable authentication completely. ++ To achieve this, first enable GSSAPI authentication for sudo in ++ sssd.conf: ++ ++ ++[domain/MYDOMAIN] ++pam_gssapi_services = sudo, sudo-i ++ ++ ++ And then enable the module in desired PAM stack ++ (e.g. /etc/pam.d/sudo and /etc/pam.d/sudo-i). ++ ++ ++... ++auth sufficient pam_sss_gss.so ++... ++ ++ ++ ++ ++ TROUBLESHOOTING ++ ++ SSSD logs, pam_sss_gss debug output and syslog may contain helpful ++ information about the error. Here are some common issues: ++ ++ ++ 1. I have KRB5CCNAME environment variable set and the authentication ++ does not work: Depending on your sudo version, it is possible that ++ sudo does not pass this variable to the PAM environment. Try adding ++ KRB5CCNAME to in /etc/sudoers or in your ++ LDAP sudo rules default options. ++ ++ ++ 2. Authentication does not work and syslog contains "Server not ++ found in Kerberos database": Kerberos is probably not able to ++ resolve correct realm for the service ticket based on the hostname. ++ Try adding the hostname directly to ++ in /etc/krb5.conf like so: ++ ++ ++ 3. Authentication does not work and syslog contains "No Kerberos ++ credentials available": You don't have any credentials that can be ++ used to obtain the required service ticket. Use kinit or autheticate ++ over SSSD to acquire those credentials. ++ ++ ++ 4. Authentication does not work and SSSD sssd-pam log contains "User ++ with UPN [$UPN] was not found." or "UPN [$UPN] does not match target ++ user [$username].": You are using credentials that can not be mapped ++ to the user that is being authenticated. Try to use kswitch to ++ select different principal, make sure you authenticated with SSSD or ++ consider disabling . ++ ++ ++[domain_realm] ++.myhostname = MYREALM ++ ++ ++ ++ ++ ++ ++ +diff --git a/src/responder/pam/pamsrv.h b/src/responder/pam/pamsrv.h +index bf4dd75b0..355329691 100644 +--- a/src/responder/pam/pamsrv.h ++++ b/src/responder/pam/pamsrv.h +@@ -145,4 +145,8 @@ errno_t pam_eval_prompting_config(struct pam_ctx *pctx, struct pam_data *pd); + + enum pam_initgroups_scheme pam_initgroups_string_to_enum(const char *str); + const char *pam_initgroup_enum_to_string(enum pam_initgroups_scheme scheme); ++ ++int pam_cmd_gssapi_init(struct cli_ctx *cli_ctx); ++int pam_cmd_gssapi_sec_ctx(struct cli_ctx *cctx); ++ + #endif /* __PAMSRV_H__ */ +diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c +index acbfc0c39..9ea488be4 100644 +--- a/src/responder/pam/pamsrv_cmd.c ++++ b/src/responder/pam/pamsrv_cmd.c +@@ -2401,6 +2401,8 @@ struct sss_cmd_table *get_pam_cmds(void) + {SSS_PAM_CHAUTHTOK, pam_cmd_chauthtok}, + {SSS_PAM_CHAUTHTOK_PRELIM, pam_cmd_chauthtok_prelim}, + {SSS_PAM_PREAUTH, pam_cmd_preauth}, ++ {SSS_GSSAPI_INIT, pam_cmd_gssapi_init}, ++ {SSS_GSSAPI_SEC_CTX, pam_cmd_gssapi_sec_ctx}, + {SSS_CLI_NULL, NULL} + }; + +diff --git a/src/responder/pam/pamsrv_gssapi.c b/src/responder/pam/pamsrv_gssapi.c +new file mode 100644 +index 000000000..099675e1c +--- /dev/null ++++ b/src/responder/pam/pamsrv_gssapi.c +@@ -0,0 +1,792 @@ ++/* ++ Authors: ++ Pavel Březina ++ ++ Copyright (C) 2020 Red Hat ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "confdb/confdb.h" ++#include "db/sysdb.h" ++#include "responder/common/responder_packet.h" ++#include "responder/common/responder.h" ++#include "responder/common/cache_req/cache_req.h" ++#include "responder/pam/pamsrv.h" ++#include "sss_client/sss_cli.h" ++#include "util/util.h" ++#include "util/sss_utf8.h" ++ ++static errno_t read_str(size_t body_len, ++ uint8_t *body, ++ size_t *pctr, ++ const char **_str) ++{ ++ size_t i; ++ ++ for (i = *pctr; i < body_len && body[i] != 0; i++) { ++ /* counting */ ++ } ++ ++ if (i >= body_len) { ++ return EINVAL; ++ } ++ ++ if (!sss_utf8_check(&body[*pctr], i - *pctr)) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Body is not UTF-8 string!\n"); ++ return EINVAL; ++ } ++ ++ *_str = (const char *)&body[*pctr]; ++ *pctr = i + 1; ++ ++ return EOK; ++} ++ ++static bool pam_gssapi_should_check_upn(struct pam_ctx *pam_ctx, ++ struct sss_domain_info *domain) ++{ ++ if (domain->gssapi_check_upn != NULL) { ++ if (strcasecmp(domain->gssapi_check_upn, "true") == 0) { ++ return true; ++ } ++ ++ if (strcasecmp(domain->gssapi_check_upn, "false") == 0) { ++ return false; ++ } ++ ++ DEBUG(SSSDBG_MINOR_FAILURE, "Invalid value for %s: %s\n", ++ CONFDB_PAM_GSSAPI_CHECK_UPN, domain->gssapi_check_upn); ++ return false; ++ } ++ ++ return pam_ctx->gssapi_check_upn; ++} ++ ++static bool pam_gssapi_allowed(struct pam_ctx *pam_ctx, ++ struct sss_domain_info *domain, ++ const char *service) ++{ ++ char **list = pam_ctx->gssapi_services; ++ ++ if (domain->gssapi_services != NULL) { ++ list = domain->gssapi_services; ++ } ++ ++ if (strcmp(service, "-") == 0) { ++ /* Dash is used as a "not set" value to allow to explicitly disable ++ * gssapi auth for specific domain. Disallow this service to be safe. ++ */ ++ DEBUG(SSSDBG_TRACE_FUNC, "Dash - was used as a PAM service name. " ++ "GSSAPI authentication is not allowed.\n"); ++ return false; ++ } ++ ++ return string_in_list(service, list, true); ++} ++ ++static char *pam_gssapi_target(TALLOC_CTX *mem_ctx, ++ struct sss_domain_info *domain) ++{ ++ return talloc_asprintf(mem_ctx, "host@%s", domain->hostname); ++} ++ ++static const char *pam_gssapi_get_upn(struct cache_req_result *result) ++{ ++ if (result->count == 0) { ++ return NULL; ++ } ++ ++ /* Canonical UPN should be available if the user has kinited through SSSD. ++ * Use it as a hint for GSSAPI. Default to empty string so it may be ++ * more easily transffered over the wire. */ ++ return ldb_msg_find_attr_as_string(result->msgs[0], SYSDB_CANONICAL_UPN, ""); ++} ++ ++static const char *pam_gssapi_get_name(struct cache_req_result *result) ++{ ++ if (result->count == 0) { ++ return NULL; ++ } ++ ++ /* Return username known to SSSD to make sure we authenticated as the same ++ * user after GSSAPI handshake. */ ++ return ldb_msg_find_attr_as_string(result->msgs[0], SYSDB_NAME, NULL); ++} ++ ++static errno_t pam_gssapi_init_parse(struct cli_protocol *pctx, ++ const char **_service, ++ const char **_username) ++{ ++ size_t body_len; ++ size_t pctr = 0; ++ uint8_t *body; ++ errno_t ret; ++ ++ sss_packet_get_body(pctx->creq->in, &body, &body_len); ++ if (body == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Invalid input\n"); ++ return EINVAL; ++ } ++ ++ ret = read_str(body_len, body, &pctr, _service); ++ if (ret != EOK) { ++ return ret; ++ } ++ ++ ret = read_str(body_len, body, &pctr, _username); ++ if (ret != EOK) { ++ return ret; ++ } ++ ++ return EOK; ++} ++ ++static errno_t pam_gssapi_init_reply(struct cli_protocol *pctx, ++ const char *domain, ++ const char *target, ++ const char *upn, ++ const char *username) ++{ ++ size_t reply_len; ++ size_t body_len; ++ size_t pctr; ++ uint8_t *body; ++ errno_t ret; ++ ++ ret = sss_packet_new(pctx->creq, 0, sss_packet_get_cmd(pctx->creq->in), ++ &pctx->creq->out); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create a new packet [%d]; %s\n", ++ ret, sss_strerror(ret)); ++ return ret; ++ } ++ ++ reply_len = strlen(username) + 1; ++ reply_len += strlen(domain) + 1; ++ reply_len += strlen(target) + 1; ++ reply_len += strlen(upn) + 1; ++ ++ ret = sss_packet_grow(pctx->creq->out, reply_len); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create response: %s\n", ++ sss_strerror(ret)); ++ return ret; ++ } ++ ++ sss_packet_get_body(pctx->creq->out, &body, &body_len); ++ ++ pctr = 0; ++ SAFEALIGN_SETMEM_STRING(&body[pctr], username, strlen(username) + 1, &pctr); ++ SAFEALIGN_SETMEM_STRING(&body[pctr], domain, strlen(domain) + 1, &pctr); ++ SAFEALIGN_SETMEM_STRING(&body[pctr], target, strlen(target) + 1, &pctr); ++ SAFEALIGN_SETMEM_STRING(&body[pctr], upn, strlen(upn) + 1, &pctr); ++ ++ return EOK; ++} ++ ++struct gssapi_init_state { ++ struct cli_ctx *cli_ctx; ++ const char *username; ++ const char *service; ++}; ++ ++static void pam_cmd_gssapi_init_done(struct tevent_req *req); ++ ++int pam_cmd_gssapi_init(struct cli_ctx *cli_ctx) ++{ ++ struct gssapi_init_state *state; ++ struct cli_protocol *pctx; ++ struct tevent_req *req; ++ const char *username; ++ const char *service; ++ const char *attrs[] = { SYSDB_NAME, SYSDB_CANONICAL_UPN, NULL }; ++ errno_t ret; ++ ++ state = talloc_zero(cli_ctx, struct gssapi_init_state); ++ if (state == NULL) { ++ return ENOMEM; ++ } ++ ++ pctx = talloc_get_type(cli_ctx->protocol_ctx, struct cli_protocol); ++ ++ ret = pam_gssapi_init_parse(pctx, &service, &username); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to parse input [%d]: %s\n", ++ ret, sss_strerror(ret)); ++ goto done; ++ } ++ ++ state->cli_ctx = cli_ctx; ++ state->service = service; ++ state->username = username; ++ ++ DEBUG(SSSDBG_TRACE_ALL, ++ "Requesting GSSAPI authentication of [%s] in service [%s]\n", ++ username, service); ++ ++ req = cache_req_user_by_name_attrs_send(cli_ctx, cli_ctx->ev, cli_ctx->rctx, ++ cli_ctx->rctx->ncache, 0, ++ NULL, username, attrs); ++ if (req == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ tevent_req_set_callback(req, pam_cmd_gssapi_init_done, state); ++ ++ ret = EOK; ++ ++done: ++ if (ret != EOK) { ++ sss_cmd_send_error(cli_ctx, ret); ++ sss_cmd_done(cli_ctx, NULL); ++ } ++ ++ return EOK; ++} ++ ++static void pam_cmd_gssapi_init_done(struct tevent_req *req) ++{ ++ struct gssapi_init_state *state; ++ struct cache_req_result *result; ++ struct cli_protocol *pctx; ++ struct pam_ctx *pam_ctx; ++ const char *username; ++ const char *upn; ++ char *target; ++ errno_t ret; ++ ++ state = tevent_req_callback_data(req, struct gssapi_init_state); ++ pctx = talloc_get_type(state->cli_ctx->protocol_ctx, struct cli_protocol); ++ pam_ctx = talloc_get_type(state->cli_ctx->rctx->pvt_ctx, struct pam_ctx); ++ ++ ret = cache_req_user_by_name_attrs_recv(state, req, &result); ++ talloc_zfree(req); ++ if (ret == ENOENT || ret == ERR_DOMAIN_NOT_FOUND) { ++ ret = ENOENT; ++ goto done; ++ } else if (ret != EOK) { ++ goto done; ++ } ++ ++ if (!pam_gssapi_allowed(pam_ctx, result->domain, state->service)) { ++ ret = ENOTSUP; ++ goto done; ++ } ++ ++ username = pam_gssapi_get_name(result); ++ if (username == NULL) { ++ /* User with no name? */ ++ ret = ERR_INTERNAL; ++ goto done; ++ } ++ ++ upn = pam_gssapi_get_upn(result); ++ if (upn == NULL) { ++ /* UPN hint may be an empty string, but not NULL. */ ++ ret = ERR_INTERNAL; ++ goto done; ++ } ++ ++ target = pam_gssapi_target(state, result->domain); ++ if (target == NULL) { ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ DEBUG(SSSDBG_TRACE_FUNC, ++ "Trying GSSAPI auth: User[%s], Domain[%s], UPN[%s], Target[%s]\n", ++ username, result->domain->name, upn, target); ++ ++ ret = pam_gssapi_init_reply(pctx, result->domain->name, target, upn, ++ username); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to construct reply [%d]: %s\n", ++ ret, sss_strerror(ret)); ++ goto done; ++ } ++ ++done: ++ DEBUG(SSSDBG_TRACE_FUNC, "Returning [%d]: %s\n", ret, sss_strerror(ret)); ++ ++ if (ret == EOK) { ++ sss_packet_set_error(pctx->creq->out, EOK); ++ } else { ++ sss_cmd_send_error(state->cli_ctx, ret); ++ } ++ ++ sss_cmd_done(state->cli_ctx, state); ++} ++ ++static void gssapi_log_status(int type, OM_uint32 status_code) ++{ ++ OM_uint32 message_context = 0; ++ gss_buffer_desc buf; ++ OM_uint32 minor; ++ ++ do { ++ gss_display_status(&minor, status_code, type, GSS_C_NO_OID, ++ &message_context, &buf); ++ DEBUG(SSSDBG_OP_FAILURE, "GSSAPI: %.*s\n", (int)buf.length, ++ (char *)buf.value); ++ gss_release_buffer(&minor, &buf); ++ } while (message_context != 0); ++} ++ ++static void gssapi_log_error(OM_uint32 major, OM_uint32 minor) ++{ ++ gssapi_log_status(GSS_C_GSS_CODE, major); ++ gssapi_log_status(GSS_C_MECH_CODE, minor); ++} ++ ++static char *gssapi_get_name(TALLOC_CTX *mem_ctx, gss_name_t gss_name) ++{ ++ gss_buffer_desc buf; ++ OM_uint32 major; ++ OM_uint32 minor; ++ char *exported; ++ ++ major = gss_display_name(&minor, gss_name, &buf, NULL); ++ if (major != GSS_S_COMPLETE) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to export name\n"); ++ return NULL; ++ } ++ ++ exported = talloc_strndup(mem_ctx, buf.value, buf.length); ++ gss_release_buffer(&minor, &buf); ++ ++ if (exported == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); ++ return NULL; ++ } ++ ++ return exported; ++} ++ ++struct gssapi_state { ++ struct cli_ctx *cli_ctx; ++ struct sss_domain_info *domain; ++ const char *username; ++ ++ char *authenticated_upn; ++ bool established; ++ gss_ctx_id_t ctx; ++}; ++ ++int gssapi_state_destructor(struct gssapi_state *state) ++{ ++ OM_uint32 minor; ++ ++ gss_delete_sec_context(&minor, &state->ctx, NULL); ++ ++ return 0; ++} ++ ++static struct gssapi_state *gssapi_get_state(struct cli_ctx *cli_ctx, ++ const char *username, ++ struct sss_domain_info *domain) ++{ ++ struct gssapi_state *state; ++ ++ state = talloc_get_type(cli_ctx->state_ctx, struct gssapi_state); ++ if (state != NULL) { ++ return state; ++ } ++ ++ state = talloc_zero(cli_ctx, struct gssapi_state); ++ if (state == NULL) { ++ return NULL; ++ } ++ ++ state->username = talloc_strdup(state, username); ++ if (state == NULL) { ++ talloc_free(state); ++ return NULL; ++ } ++ ++ state->domain = domain; ++ state->cli_ctx = cli_ctx; ++ state->ctx = GSS_C_NO_CONTEXT; ++ talloc_set_destructor(state, gssapi_state_destructor); ++ ++ cli_ctx->state_ctx = state; ++ ++ return state; ++} ++ ++static errno_t gssapi_get_creds(const char *keytab, ++ const char *target, ++ gss_cred_id_t *_creds) ++{ ++ gss_key_value_set_desc cstore = {0, NULL}; ++ gss_key_value_element_desc el; ++ gss_buffer_desc name_buf; ++ gss_name_t name = GSS_C_NO_NAME; ++ OM_uint32 major; ++ OM_uint32 minor; ++ errno_t ret; ++ ++ if (keytab != NULL) { ++ el.key = "keytab"; ++ el.value = keytab; ++ cstore.count = 1; ++ cstore.elements = ⪙ ++ } ++ ++ if (target != NULL) { ++ name_buf.value = discard_const(target); ++ name_buf.length = strlen(target); ++ ++ major = gss_import_name(&minor, &name_buf, GSS_C_NT_HOSTBASED_SERVICE, ++ &name); ++ if (GSS_ERROR(major)) { ++ DEBUG(SSSDBG_OP_FAILURE, "Could not import name [%s] " ++ "[maj:0x%x, min:0x%x]\n", target, major, minor); ++ ++ gssapi_log_error(major, minor); ++ ++ ret = EIO; ++ goto done; ++ } ++ } ++ ++ major = gss_acquire_cred_from(&minor, name, GSS_C_INDEFINITE, ++ GSS_C_NO_OID_SET, GSS_C_ACCEPT, &cstore, ++ _creds, NULL, NULL); ++ if (GSS_ERROR(major)) { ++ DEBUG(SSSDBG_OP_FAILURE, "Unable to read credentials from [%s] " ++ "[maj:0x%x, min:0x%x]\n", keytab ? keytab : "default", ++ major, minor); ++ ++ gssapi_log_error(major, minor); ++ ++ ret = EIO; ++ goto done; ++ } ++ ++ ret = EOK; ++ ++done: ++ gss_release_name(&minor, &name); ++ ++ return ret; ++} ++ ++static errno_t ++gssapi_handshake(struct gssapi_state *state, ++ struct cli_protocol *pctx, ++ const char *keytab, ++ const char *target, ++ uint8_t *gss_data, ++ size_t gss_data_len) ++{ ++ OM_uint32 flags = GSS_C_MUTUAL_FLAG; ++ gss_buffer_desc output = GSS_C_EMPTY_BUFFER; ++ gss_buffer_desc input; ++ gss_name_t client_name; ++ gss_cred_id_t creds; ++ OM_uint32 ret_flags; ++ gss_OID mech_type; ++ OM_uint32 major; ++ OM_uint32 minor; ++ errno_t ret; ++ ++ input.value = gss_data; ++ input.length = gss_data_len; ++ ++ ret = gssapi_get_creds(keytab, target, &creds); ++ if (ret != EOK) { ++ return ret; ++ } ++ ++ major = gss_accept_sec_context(&minor, &state->ctx, creds, ++ &input, NULL, &client_name, &mech_type, ++ &output, &ret_flags, NULL, NULL); ++ if (major == GSS_S_CONTINUE_NEEDED || output.length > 0) { ++ ret = sss_packet_set_body(pctx->creq->out, output.value, output.length); ++ if (ret != EOK) { ++ goto done; ++ } ++ } ++ ++ if (GSS_ERROR(major)) { ++ DEBUG(SSSDBG_OP_FAILURE, "Unable to establish GSS context " ++ "[maj:0x%x, min:0x%x]\n", major, minor); ++ ++ gssapi_log_error(major, minor); ++ ret = EIO; ++ goto done; ++ } ++ ++ if (major == GSS_S_CONTINUE_NEEDED) { ++ ret = EOK; ++ goto done; ++ } else if (major != GSS_S_COMPLETE) { ++ DEBUG(SSSDBG_OP_FAILURE, "Unable to establish GSS context, unexpected " ++ "value: 0x%x\n", major); ++ ret = EIO; ++ goto done; ++ } ++ ++ if ((ret_flags & flags) != flags) { ++ DEBUG(SSSDBG_MINOR_FAILURE, ++ "Negotiated context does not support requested flags\n"); ++ state->established = false; ++ ret = EIO; ++ goto done; ++ } ++ ++ state->authenticated_upn = gssapi_get_name(state, client_name); ++ if (state->authenticated_upn == NULL) { ++ state->established = false; ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ DEBUG(SSSDBG_TRACE_FUNC, "Security context established with [%s]\n", ++ state->authenticated_upn); ++ ++ state->established = true; ++ ret = EOK; ++ ++done: ++ gss_release_cred(&minor, &creds); ++ gss_release_buffer(&minor, &output); ++ ++ return ret; ++} ++ ++static errno_t pam_cmd_gssapi_sec_ctx_parse(struct cli_protocol *pctx, ++ const char **_pam_service, ++ const char **_username, ++ const char **_domain, ++ uint8_t **_gss_data, ++ size_t *_gss_data_len) ++{ ++ size_t body_len; ++ uint8_t *body; ++ size_t pctr; ++ errno_t ret; ++ ++ sss_packet_get_body(pctx->creq->in, &body, &body_len); ++ if (body == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Invalid input\n"); ++ return EINVAL; ++ } ++ ++ pctr = 0; ++ ret = read_str(body_len, body, &pctr, _pam_service); ++ if (ret != EOK) { ++ return ret; ++ } ++ ++ ret = read_str(body_len, body, &pctr, _username); ++ if (ret != EOK) { ++ return ret; ++ } ++ ++ ret = read_str(body_len, body, &pctr, _domain); ++ if (ret != EOK) { ++ return ret; ++ } ++ ++ *_gss_data = (pctr == body_len) ? NULL : body + pctr; ++ *_gss_data_len = body_len - pctr; ++ ++ return EOK; ++} ++ ++static void pam_cmd_gssapi_sec_ctx_done(struct tevent_req *req); ++ ++int ++pam_cmd_gssapi_sec_ctx(struct cli_ctx *cli_ctx) ++{ ++ struct sss_domain_info *domain; ++ struct gssapi_state *state; ++ struct cli_protocol *pctx; ++ struct pam_ctx *pam_ctx; ++ struct tevent_req *req; ++ const char *pam_service; ++ const char *domain_name; ++ const char *username; ++ char *target; ++ size_t gss_data_len; ++ uint8_t *gss_data; ++ errno_t ret; ++ ++ pctx = talloc_get_type(cli_ctx->protocol_ctx, struct cli_protocol); ++ pam_ctx = talloc_get_type(cli_ctx->rctx->pvt_ctx, struct pam_ctx); ++ ++ ret = sss_packet_new(pctx->creq, 0, sss_packet_get_cmd(pctx->creq->in), ++ &pctx->creq->out); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create a new packet [%d]; %s\n", ++ ret, sss_strerror(ret)); ++ return ret; ++ } ++ ++ ret = pam_cmd_gssapi_sec_ctx_parse(pctx, &pam_service, &username, ++ &domain_name, &gss_data, &gss_data_len); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, "Unable to parse input data [%d]: %s\n", ++ ret, sss_strerror(ret)); ++ goto done; ++ } ++ ++ domain = find_domain_by_name(cli_ctx->rctx->domains, domain_name, false); ++ if (domain == NULL) { ++ ret = EINVAL; ++ goto done; ++ } ++ ++ if (!pam_gssapi_allowed(pam_ctx, domain, pam_service)) { ++ ret = ENOTSUP; ++ goto done; ++ } ++ ++ target = pam_gssapi_target(cli_ctx, domain); ++ if (target == NULL) { ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ state = gssapi_get_state(cli_ctx, username, domain); ++ if (state == NULL) { ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ if (strcmp(username, state->username) != 0 || state->domain != domain) { ++ /* This should not happen, but be paranoid. */ ++ DEBUG(SSSDBG_CRIT_FAILURE, "Different input user then who initiated " ++ "the request!\n"); ++ ret = EPERM; ++ goto done; ++ } ++ ++ if (state->established) { ++ DEBUG(SSSDBG_MINOR_FAILURE, ++ "Security context is already established\n"); ++ ret = EPERM; ++ goto done; ++ } ++ ++ ret = gssapi_handshake(state, pctx, domain->krb5_keytab, target, gss_data, ++ gss_data_len); ++ if (ret != EOK || !state->established) { ++ goto done; ++ } ++ ++ if (!pam_gssapi_should_check_upn(pam_ctx, domain)) { ++ /* We are done. */ ++ goto done; ++ } ++ ++ /* We have established the security context. Now check the the principal ++ * used for authorization can be associated with the user. We have ++ * already done initgroups before so we could just search the sysdb ++ * directly, but use cache req to avoid looking up a possible expired ++ * object if the handshake took longer. */ ++ ++ DEBUG(SSSDBG_TRACE_FUNC, "Checking that target user matches UPN\n"); ++ ++ req = cache_req_user_by_upn_send(cli_ctx, cli_ctx->ev, cli_ctx->rctx, ++ cli_ctx->rctx->ncache, 0, DOM_TYPE_POSIX, ++ domain->name, state->authenticated_upn); ++ if (req == NULL) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory!\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ tevent_req_set_callback(req, pam_cmd_gssapi_sec_ctx_done, state); ++ ++ return EOK; ++ ++done: ++ DEBUG(SSSDBG_TRACE_FUNC, "Returning [%d]: %s\n", ret, sss_strerror(ret)); ++ ++ if (ret == EOK) { ++ sss_packet_set_error(pctx->creq->out, EOK); ++ } else { ++ sss_cmd_send_error(cli_ctx, ret); ++ } ++ ++ sss_cmd_done(cli_ctx, NULL); ++ return EOK; ++} ++ ++static void pam_cmd_gssapi_sec_ctx_done(struct tevent_req *req) ++{ ++ struct gssapi_state *state; ++ struct cache_req_result *result; ++ struct cli_protocol *pctx; ++ const char *name; ++ errno_t ret; ++ ++ state = tevent_req_callback_data(req, struct gssapi_state); ++ pctx = talloc_get_type(state->cli_ctx->protocol_ctx, struct cli_protocol); ++ ++ ret = cache_req_user_by_upn_recv(state, req, &result); ++ talloc_zfree(req); ++ if (ret == ENOENT || ret == ERR_DOMAIN_NOT_FOUND) { ++ /* We have no match. Return failure. */ ++ DEBUG(SSSDBG_TRACE_FUNC, "User with UPN [%s] was not found. " ++ "Authentication failed.\n", state->authenticated_upn); ++ ret = EACCES; ++ goto done; ++ } else if (ret != EOK) { ++ /* Generic error. Return failure. */ ++ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to lookup user by UPN [%d]: %s\n", ++ ret, sss_strerror(ret)); ++ goto done; ++ } ++ ++ /* Check that username match. */ ++ name = ldb_msg_find_attr_as_string(result->msgs[0], SYSDB_NAME, NULL); ++ if (name == NULL || strcmp(name, state->username) != 0) { ++ DEBUG(SSSDBG_TRACE_FUNC, "UPN [%s] does not match target user [%s]. " ++ "Authentication failed.\n", state->authenticated_upn, ++ state->username); ++ ret = EACCES; ++ goto done; ++ } ++ ++ DEBUG(SSSDBG_TRACE_FUNC, "User [%s] match UPN [%s]. Authentication was " ++ "successful.\n", state->username, state->authenticated_upn); ++ ++ ret = EOK; ++ ++done: ++ DEBUG(SSSDBG_TRACE_FUNC, "Returning [%d]: %s\n", ret, sss_strerror(ret)); ++ ++ if (ret == EOK) { ++ sss_packet_set_error(pctx->creq->out, EOK); ++ } else { ++ sss_cmd_send_error(state->cli_ctx, ret); ++ } ++ ++ sss_cmd_done(state->cli_ctx, state); ++} +diff --git a/src/sss_client/pam_sss_gss.c b/src/sss_client/pam_sss_gss.c +new file mode 100644 +index 000000000..cd38db7da +--- /dev/null ++++ b/src/sss_client/pam_sss_gss.c +@@ -0,0 +1,588 @@ ++/* ++ Authors: ++ Pavel Březina ++ ++ Copyright (C) 2020 Red Hat ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "util/sss_format.h" ++#include "sss_client/sss_cli.h" ++ ++bool debug_enabled; ++ ++#define TRACE(pamh, fmt, ...) do { \ ++ if (debug_enabled) { \ ++ pam_info(pamh, "pam_sss_gss: " fmt, ## __VA_ARGS__); \ ++ } \ ++} while (0) ++ ++#define ERROR(pamh, fmt, ...) do { \ ++ if (debug_enabled) { \ ++ pam_error(pamh, "pam_sss_gss: " fmt, ## __VA_ARGS__); \ ++ pam_syslog(pamh, LOG_ERR, fmt, ## __VA_ARGS__); \ ++ } \ ++} while (0) ++ ++static bool switch_euid(pam_handle_t *pamh, uid_t current, uid_t desired) ++{ ++ int ret; ++ ++ TRACE(pamh, "Switching euid from %" SPRIuid " to %" SPRIuid, current, ++ desired); ++ ++ if (current == desired) { ++ return true; ++ } ++ ++ ret = seteuid(desired); ++ if (ret != 0) { ++ ERROR(pamh, "Unable to set euid to %" SPRIuid, desired); ++ return false; ++ } ++ ++ return true; ++} ++ ++static const char *get_item_as_string(pam_handle_t *pamh, int item) ++{ ++ const char *str; ++ int ret; ++ ++ ret = pam_get_item(pamh, item, (void *)&str); ++ if (ret != PAM_SUCCESS || str == NULL || str[0] == '\0') { ++ return NULL; ++ } ++ ++ return str; ++} ++ ++static errno_t string_to_gss_name(pam_handle_t *pamh, ++ const char *target, ++ gss_OID type, ++ gss_name_t *_name) ++{ ++ gss_buffer_desc name_buf; ++ OM_uint32 major; ++ OM_uint32 minor; ++ ++ name_buf.value = (void *)(uintptr_t)target; ++ name_buf.length = strlen(target); ++ major = gss_import_name(&minor, &name_buf, type, _name); ++ if (GSS_ERROR(major)) { ++ ERROR(pamh, "Could not convert target to GSS name"); ++ return EIO; ++ } ++ ++ return EOK; ++} ++ ++static void gssapi_log_status(pam_handle_t *pamh, ++ int type, ++ OM_uint32 status_code) ++{ ++ gss_buffer_desc buf; ++ OM_uint32 message_context; ++ OM_uint32 minor; ++ ++ message_context = 0; ++ do { ++ gss_display_status(&minor, status_code, type, GSS_C_NO_OID, ++ &message_context, &buf); ++ ERROR(pamh, "GSSAPI: %.*s", (int)buf.length, (char *)buf.value); ++ gss_release_buffer(&minor, &buf); ++ } while (message_context != 0); ++} ++ ++static void gssapi_log_error(pam_handle_t *pamh, ++ OM_uint32 major, ++ OM_uint32 minor) ++{ ++ gssapi_log_status(pamh, GSS_C_GSS_CODE, major); ++ gssapi_log_status(pamh, GSS_C_MECH_CODE, minor); ++} ++ ++static errno_t gssapi_get_creds(pam_handle_t *pamh, ++ const char *ccache, ++ const char *target, ++ const char *upn, ++ gss_cred_id_t *_creds) ++{ ++ gss_key_value_set_desc cstore = {0, NULL}; ++ gss_key_value_element_desc el; ++ gss_name_t name = GSS_C_NO_NAME; ++ OM_uint32 major; ++ OM_uint32 minor; ++ errno_t ret; ++ ++ if (upn != NULL && upn[0] != '\0') { ++ TRACE(pamh, "Acquiring credentials for principal [%s]", upn); ++ ret = string_to_gss_name(pamh, upn, GSS_C_NT_USER_NAME, &name); ++ if (ret != EOK) { ++ goto done; ++ } ++ } else { ++ TRACE(pamh, "Acquiring credentials, principal name will be derived"); ++ } ++ ++ if (ccache != NULL) { ++ el.key = "ccache"; ++ el.value = ccache; ++ cstore.count = 1; ++ cstore.elements = ⪙ ++ } ++ ++ major = gss_acquire_cred_from(&minor, name, GSS_C_INDEFINITE, ++ GSS_C_NO_OID_SET, GSS_C_INITIATE, ++ &cstore, _creds, NULL, NULL); ++ if (GSS_ERROR(major)) { ++ /* TODO: Do not hardcode the error code. */ ++ if (minor == 2529639053 && name != GSS_C_NO_NAME) { ++ /* Hint principal was not found. Try again and let GSSAPI choose. */ ++ TRACE(pamh, "Principal [%s] was not found in ccache", upn); ++ ret = gssapi_get_creds(pamh, ccache, target, NULL, _creds); ++ goto done; ++ } else { ++ ERROR(pamh, "Unable to read credentials from [%s] " ++ "[maj:0x%x, min:0x%x]", ccache == NULL ? "default" : ccache, ++ major, minor); ++ ++ gssapi_log_error(pamh, major, minor); ++ ret = EIO; ++ goto done; ++ } ++ } ++ ++ ret = EOK; ++ ++done: ++ gss_release_name(&minor, &name); ++ ++ return ret; ++} ++ ++static errno_t sssd_gssapi_init_send(pam_handle_t *pamh, ++ const char *pam_service, ++ const char *pam_user, ++ uint8_t **_reply, ++ size_t *_reply_len) ++{ ++ struct sss_cli_req_data req_data; ++ size_t service_len; ++ size_t user_len; ++ uint8_t *data; ++ errno_t ret; ++ int ret_errno; ++ ++ if (pam_service == NULL || pam_user == NULL) { ++ return EINVAL; ++ } ++ ++ service_len = strlen(pam_service) + 1; ++ user_len = strlen(pam_user) + 1; ++ ++ req_data.len = (service_len + user_len) * sizeof(char); ++ data = (uint8_t*)malloc(req_data.len); ++ if (data == NULL) { ++ return ENOMEM; ++ } ++ ++ memcpy(data, pam_service, service_len); ++ memcpy(data + service_len, pam_user, user_len); ++ ++ req_data.data = data; ++ ++ ret = sss_pam_make_request(SSS_GSSAPI_INIT, &req_data, _reply, _reply_len, ++ &ret_errno); ++ free(data); ++ if (ret != PAM_SUCCESS) { ++ if (ret_errno == ENOTSUP) { ++ TRACE(pamh, "GSSAPI authentication is not supported for user %s " ++ "and service %s", pam_user, pam_service); ++ return ret_errno; ++ } ++ ++ ERROR(pamh, "Communication error [%d, %d]: %s; %s", ret, ret_errno, ++ pam_strerror(pamh, ret), strerror(ret_errno)); ++ ++ return (ret_errno != EOK) ? ret_errno : EIO; ++ } ++ ++ return ret_errno; ++} ++ ++static errno_t sssd_gssapi_init_recv(uint8_t *reply, ++ size_t reply_len, ++ char **_username, ++ char **_domain, ++ char **_target, ++ char **_upn) ++{ ++ char *username = NULL; ++ char *domain = NULL; ++ char *target = NULL; ++ char *upn = NULL; ++ const char *buf; ++ size_t pctr = 0; ++ size_t dlen; ++ errno_t ret; ++ ++ username = malloc(reply_len * sizeof(char)); ++ domain = malloc(reply_len * sizeof(char)); ++ target = malloc(reply_len * sizeof(char)); ++ upn = malloc(reply_len * sizeof(char)); ++ if (username == NULL || domain == NULL || target == NULL || upn == NULL) { ++ return ENOMEM; ++ } ++ ++ buf = (const char*)reply; ++ ++ dlen = reply_len; ++ ret = sss_readrep_copy_string(buf, &pctr, &reply_len, &dlen, &username, ++ NULL); ++ if (ret != EOK) { ++ goto done; ++ } ++ ++ dlen = reply_len; ++ ret = sss_readrep_copy_string(buf, &pctr, &reply_len, &dlen, &domain, NULL); ++ if (ret != EOK) { ++ goto done; ++ } ++ ++ dlen = reply_len; ++ ret = sss_readrep_copy_string(buf, &pctr, &reply_len, &dlen, &target, NULL); ++ if (ret != EOK) { ++ goto done; ++ } ++ ++ dlen = reply_len; ++ ret = sss_readrep_copy_string(buf, &pctr, &reply_len, &dlen, &upn, NULL); ++ if (ret != EOK) { ++ goto done; ++ } ++ ++ *_username = username; ++ *_domain = domain; ++ *_target = target; ++ *_upn = upn; ++ ++done: ++ if (ret != EOK) { ++ free(username); ++ free(domain); ++ free(target); ++ free(upn); ++ } ++ ++ return ret; ++} ++ ++static errno_t sssd_gssapi_init(pam_handle_t *pamh, ++ const char *pam_service, ++ const char *pam_user, ++ char **_username, ++ char **_domain, ++ char **_target, ++ char **_upn) ++{ ++ size_t reply_len; ++ uint8_t *reply; ++ errno_t ret; ++ ++ ret = sssd_gssapi_init_send(pamh, pam_service, pam_user, &reply, ++ &reply_len); ++ if (ret != EOK) { ++ return ret; ++ } ++ ++ ret = sssd_gssapi_init_recv(reply, reply_len, _username, _domain, _target, ++ _upn); ++ free(reply); ++ ++ return ret; ++} ++ ++static errno_t sssd_establish_sec_ctx_send(pam_handle_t *pamh, ++ const char *pam_service, ++ const char *username, ++ const char *domain, ++ const void *gss_data, ++ size_t gss_data_len, ++ void **_reply, ++ size_t *_reply_len) ++{ ++ struct sss_cli_req_data req_data; ++ size_t username_len; ++ size_t service_len; ++ size_t domain_len; ++ uint8_t *data; ++ int ret_errno; ++ int ret; ++ ++ service_len = strlen(pam_service) + 1; ++ username_len = strlen(username) + 1; ++ domain_len = strlen(domain) + 1; ++ ++ req_data.len = (service_len + username_len + domain_len) * sizeof(char) ++ + gss_data_len; ++ data = malloc(req_data.len); ++ if (data == NULL) { ++ return ENOMEM; ++ } ++ ++ memcpy(data, pam_service, service_len); ++ memcpy(data + service_len, username, username_len); ++ memcpy(data + service_len + username_len, domain, domain_len); ++ memcpy(data + service_len + username_len + domain_len, gss_data, ++ gss_data_len); ++ ++ req_data.data = data; ++ ret = sss_pam_make_request(SSS_GSSAPI_SEC_CTX, &req_data, (uint8_t**)_reply, ++ _reply_len, &ret_errno); ++ free(data); ++ if (ret != PAM_SUCCESS) { ++ /* ENOTSUP should not happend here so let's keep it as generic error. */ ++ ERROR(pamh, "Communication error [%d, %d]: %s; %s", ret, ret_errno, ++ pam_strerror(pamh, ret), strerror(ret_errno)); ++ ++ return (ret_errno != EOK) ? ret_errno : EIO; ++ } ++ ++ return ret_errno; ++} ++ ++static int sssd_establish_sec_ctx(pam_handle_t *pamh, ++ const char *ccache, ++ const char *pam_service, ++ const char *username, ++ const char *domain, ++ const char *target, ++ const char *upn) ++{ ++ gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; ++ gss_buffer_desc input = GSS_C_EMPTY_BUFFER; ++ gss_buffer_desc output = GSS_C_EMPTY_BUFFER; ++ OM_uint32 flags = GSS_C_MUTUAL_FLAG; ++ gss_name_t gss_name; ++ gss_cred_id_t creds; ++ OM_uint32 ret_flags; ++ OM_uint32 major; ++ OM_uint32 minor; ++ int ret; ++ ++ ret = gssapi_get_creds(pamh, ccache, target, upn, &creds); ++ if (ret != EOK) { ++ return ret; ++ } ++ ++ ret = string_to_gss_name(pamh, target, GSS_C_NT_HOSTBASED_SERVICE, &gss_name); ++ if (ret != 0) { ++ return ret; ++ } ++ ++ do { ++ major = gss_init_sec_context(&minor, creds, &ctx, ++ gss_name, GSS_C_NO_OID, flags, 0, NULL, ++ &input, NULL, &output, ++ &ret_flags, NULL); ++ ++ free(input.value); ++ memset(&input, 0, sizeof(gss_buffer_desc)); ++ ++ if (GSS_ERROR(major)) { ++ ERROR(pamh, "Unable to establish GSS context [maj:0x%x, min:0x%x]", ++ major, minor); ++ gssapi_log_error(pamh, major, minor); ++ ret = EIO; ++ goto done; ++ } else if (major == GSS_S_CONTINUE_NEEDED || output.length > 0) { ++ ret = sssd_establish_sec_ctx_send(pamh, pam_service, ++ username, domain, ++ output.value, output.length, ++ &input.value, &input.length); ++ gss_release_buffer(NULL, &output); ++ if (ret != EOK) { ++ goto done; ++ } ++ } ++ } while (major != GSS_S_COMPLETE); ++ ++ if ((ret_flags & flags) != flags) { ++ ERROR(pamh, "Negotiated context does not support requested flags\n"); ++ ret = EIO; ++ goto done; ++ } ++ ++ ret = EOK; ++ ++done: ++ gss_delete_sec_context(&minor, &ctx, NULL); ++ gss_release_name(&minor, &gss_name); ++ ++ return ret; ++} ++ ++static int errno_to_pam(pam_handle_t *pamh, errno_t ret) ++{ ++ switch (ret) { ++ case EOK: ++ TRACE(pamh, "Authentication successful"); ++ return PAM_SUCCESS; ++ case ENOENT: ++ TRACE(pamh, "User not found"); ++ return PAM_USER_UNKNOWN; ++ case ENOTSUP: ++ TRACE(pamh, "GSSAPI authentication is not enabled " ++ "for given user and service"); ++ return PAM_USER_UNKNOWN; ++ case ESSS_NO_SOCKET: ++ TRACE(pamh, "SSSD socket does not exist"); ++ return PAM_AUTHINFO_UNAVAIL; ++ case EPERM: ++ TRACE(pamh, "Authentication failed"); ++ return PAM_AUTH_ERR; ++ default: ++ TRACE(pamh, "System error [%d]: %s", ++ ret, strerror(ret)); ++ return PAM_SYSTEM_ERR; ++ } ++} ++ ++int pam_sm_authenticate(pam_handle_t *pamh, ++ int flags, ++ int argc, ++ const char **argv) ++{ ++ const char *pam_service; ++ const char *pam_user; ++ const char *ccache; ++ char *username = NULL; ++ char *domain = NULL; ++ char *target = NULL; ++ char *upn = NULL; ++ uid_t uid; ++ uid_t euid; ++ errno_t ret; ++ ++ debug_enabled = false; ++ for (int i = 0; i < argc; i++) { ++ if (strcmp(argv[i], "debug") == 0) { ++ debug_enabled = true; ++ break; ++ } ++ } ++ ++ ++ /* Get non-default ccache if specified, may be NULL. */ ++ ccache = getenv("KRB5CCNAME"); ++ ++ uid = getuid(); ++ euid = geteuid(); ++ ++ /* Read PAM data. */ ++ pam_service = get_item_as_string(pamh, PAM_SERVICE); ++ pam_user = get_item_as_string(pamh, PAM_USER); ++ if (pam_service == NULL || pam_user == NULL) { ++ ERROR(pamh, "Unable to get PAM data!"); ++ ret = EINVAL; ++ goto done; ++ } ++ ++ /* Initialize GSSAPI authentication with SSSD. Get user domain ++ * and target GSS service name. */ ++ TRACE(pamh, "Initializing GSSAPI authentication with SSSD"); ++ ret = sssd_gssapi_init(pamh, pam_service, pam_user, &username, &domain, ++ &target, &upn); ++ if (ret != EOK) { ++ goto done; ++ } ++ ++ /* PAM is often called from set-user-id applications (sudo, su). we want to ++ * make sure that we access credentials of the caller (real uid). */ ++ if (!switch_euid(pamh, euid, uid)) { ++ ret = EFAULT; ++ goto done; ++ } ++ ++ /* Authenticate the user by estabilishing security context. Authorization is ++ * expected to be done by other modules through pam_access. */ ++ TRACE(pamh, "Trying to establish security context"); ++ TRACE(pamh, "SSSD User name: %s", username); ++ TRACE(pamh, "User domain: %s", domain); ++ TRACE(pamh, "User principal: %s", upn); ++ TRACE(pamh, "Target name: %s", target); ++ TRACE(pamh, "Using ccache: %s", ccache == NULL ? "default" : ccache); ++ ret = sssd_establish_sec_ctx(pamh, ccache, pam_service, ++ username, domain, target, upn); ++ ++ /* Restore original euid. */ ++ if (!switch_euid(pamh, uid, euid)) { ++ ret = EFAULT; ++ goto done; ++ } ++ ++done: ++ sss_pam_close_fd(); ++ free(domain); ++ free(target); ++ free(upn); ++ ++ return errno_to_pam(pamh, ret); ++} ++ ++int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) ++{ ++ return PAM_IGNORE; ++} ++ ++int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv) ++{ ++ return PAM_IGNORE; ++} ++ ++int pam_sm_open_session(pam_handle_t *pamh, ++ int flags, ++ int argc, ++ const char **argv) ++{ ++ return PAM_IGNORE; ++} ++ ++int pam_sm_close_session(pam_handle_t *pamh, ++ int flags, ++ int argc, ++ const char **argv) ++{ ++ return PAM_IGNORE; ++} ++ ++int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) ++{ ++ return PAM_IGNORE; ++} +diff --git a/src/sss_client/pam_sss_gss.exports b/src/sss_client/pam_sss_gss.exports +new file mode 100644 +index 000000000..9afa106be +--- /dev/null ++++ b/src/sss_client/pam_sss_gss.exports +@@ -0,0 +1,4 @@ ++{ ++ global: ++ *; ++}; +diff --git a/src/sss_client/sss_cli.h b/src/sss_client/sss_cli.h +index d897f43b7..2c3c71bc4 100644 +--- a/src/sss_client/sss_cli.h ++++ b/src/sss_client/sss_cli.h +@@ -233,6 +233,8 @@ enum sss_cli_command { + * an authentication request to find + * out which authentication methods + * are available for the given user. */ ++ SSS_GSSAPI_INIT = 0x00FA, /**< Initialize GSSAPI authentication. */ ++ SSS_GSSAPI_SEC_CTX = 0x00FB, /**< Establish GSSAPI security ctx. */ + + /* PAC responder calls */ + SSS_PAC_ADD_PAC_USER = 0x0101, +@@ -721,4 +723,10 @@ errno_t sss_readrep_copy_string(const char *in, + char **out, + size_t *size); + ++enum pam_gssapi_cmd { ++ PAM_GSSAPI_GET_NAME, ++ PAM_GSSAPI_INIT, ++ PAM_GSSAPI_SENTINEL ++}; ++ + #endif /* _SSSCLI_H */ +diff --git a/src/tests/dlopen-tests.c b/src/tests/dlopen-tests.c +index ccf52abe9..bffa02188 100644 +--- a/src/tests/dlopen-tests.c ++++ b/src/tests/dlopen-tests.c +@@ -47,6 +47,7 @@ struct so { + { "libnss_sss.so", { LIBPFX"libnss_sss.so", NULL } }, + { "libsss_certmap.so", { LIBPFX"libsss_certmap.so", NULL } }, + { "pam_sss.so", { LIBPFX"pam_sss.so", NULL } }, ++ { "pam_sss_gss.so", { LIBPFX"pam_sss_gss.so", NULL } }, + #ifdef BUILD_WITH_LIBSECRET + { "libsss_secrets.so", { LIBPFX"libsss_secrets.so", NULL } }, + #endif /* BUILD_WITH_LIBSECRET */ +-- +2.21.3 + diff --git a/SPECS/sssd.spec b/SPECS/sssd.spec index 26bb823..a05bfb9 100644 --- a/SPECS/sssd.spec +++ b/SPECS/sssd.spec @@ -26,7 +26,7 @@ Name: sssd Version: 2.4.0 -Release: 3%{?dist} +Release: 5%{?dist} Group: Applications/System Summary: System Security Services Daemon License: GPLv3+ @@ -42,6 +42,25 @@ Patch0005: 0005-negcache-make-sure-domain-config-does-not-leak-into-.patch Patch0006: 0006-utils-add-SSS_GND_SUBDOMAINS-flag-for-get_next_domai.patch Patch0007: 0007-negcache-make-sure-short-names-are-added-to-sub-doma.patch Patch0008: 0008-negcache-do-not-use-default_domain_suffix.patch +Patch0009: 0009-kcm-decode-base64-encoded-secret-on-upgrade-path.patch +Patch0010: 0010-nss-check-if-groups-are-filtered-during-initgroups.patch +Patch0011: 0011-ifp-fix-use-after-free.patch +Patch0012: 0012-ifp-fix-original-fix-use-after-free.patch +Patch0013: 0013-pam_sss-use-unique-id-for-gdm-choice-list.patch +Patch0014: 0014-authtok-add-label-to-Smartcard-token.patch +Patch0015: 0015-pam_sss-add-certificate-label-to-reply-to-pam_sss.patch +Patch0016: 0016-add-tests-multiple-certs-same-id.patch +Patch0017: 0017-data_provider_be-Add-random-offset-default.patch +Patch0018: 0018-data_provider_be-MAN-page-update.patch +Patch0019: 0019-logs-review.patch +Patch0020: 0020-sss_format.h-include-config.h.patch +Patch0021: 0021-packet-add-sss_packet_set_body.patch +Patch0022: 0022-domain-store-hostname-and-keytab-path.patch +Patch0023: 0023-cache_req-add-helper-to-call-user-by-upn-search.patch +Patch0024: 0024-pam-fix-typo-in-debug-message.patch +Patch0025: 0025-pam-add-pam_gssapi_services-option.patch +Patch0026: 0026-pam-add-pam_gssapi_check_upn-option.patch +Patch0027: 0027-pam-add-pam_sss_gss-module-for-gssapi-authentication.patch ### Downstream Patches ### @@ -940,6 +959,7 @@ done %license src/sss_client/COPYING src/sss_client/COPYING.LESSER %{_libdir}/libnss_sss.so.2 %{_libdir}/security/pam_sss.so +%{_libdir}/security/pam_sss_gss.so %{_libdir}/krb5/plugins/libkrb5/sssd_krb5_locator_plugin.so %{_libdir}/krb5/plugins/authdata/sssd_pac_plugin.so %dir %{_libdir}/cifs-utils @@ -950,6 +970,7 @@ done %dir %{_libdir}/%{name}/modules %{_libdir}/%{name}/modules/sssd_krb5_localauth_plugin.so %{_mandir}/man8/pam_sss.8* +%{_mandir}/man8/pam_sss_gss.8* %{_mandir}/man8/sssd_krb5_locator_plugin.8* %files -n libsss_sudo @@ -1215,6 +1236,17 @@ fi %{_libdir}/%{name}/modules/libwbclient.so %changelog +* Mon Dec 28 2020 Alexey Tikhonov - 2.4.0-5 +- Resolves: rhbz#1631410 - Can't login with smartcard with multiple certs having same ID value +- Resolves: rhbz#1884213 - [RFE] add offline_timeout_max config option to control offline interval backoff (additional patches) +- Resolves: rhbz#1893159 - Default debug level should report all errors / failures +- Resolves: rhbz#1893698 - [RFE] sudo kerberos authentication + +* Mon Dec 21 2020 Alexey Tikhonov - 2.4.0-4 +- Resolves: rhbz#1876514 - High CPU utilization by the sssd_kcm process +- Resolves: rhbz#1876658 - filter_groups option partially filters the group from 'id' output of the user because gidNumber still appears in 'id' output [RHEL 8] +- Resolves: rhbz#1895001 - User lookups over the InfoPipe responder fail intermittently + * Mon Dec 07 2020 Alexey Tikhonov - 2.4.0-3 - Resolves: rhbz#1900733 - sssd_be segfaults at be_refresh_get_values_ex() due to NULL ptrs in results of sysdb_search_with_ts_attr() - Resolves: rhbz#1876514 - High CPU utilization by the sssd_kcm process