diff --git a/SOURCES/0008-DP-reduce-log-level-in-case-a-responder-asks.patch b/SOURCES/0008-DP-reduce-log-level-in-case-a-responder-asks.patch new file mode 100644 index 0000000..1c6e7bd --- /dev/null +++ b/SOURCES/0008-DP-reduce-log-level-in-case-a-responder-asks.patch @@ -0,0 +1,28 @@ +From 39cd0baa06742b349ed763aa40ea4de366e80f1a Mon Sep 17 00:00:00 2001 +From: Alexey Tikhonov +Date: Thu, 7 Dec 2023 09:47:25 +0100 +Subject: [PATCH] DP: reduce log level in case a responder asks for unknown + domain + +Since 9358a74d3a56c738890353aaf6bc956bfe72df99 a domain might be +skipped by 'ad_enabled_domains' option + +Reviewed-by: Sumit Bose +--- + src/providers/data_provider/dp_request.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/providers/data_provider/dp_request.c b/src/providers/data_provider/dp_request.c +index df2db26662..9c0fcf1f52 100644 +--- a/src/providers/data_provider/dp_request.c ++++ b/src/providers/data_provider/dp_request.c +@@ -204,7 +204,8 @@ dp_req_new(TALLOC_CTX *mem_ctx, + if (domainname != NULL) { + dp_req->domain = find_domain_by_name(be_ctx->domain, domainname, true); + if (dp_req->domain == NULL) { +- DEBUG(SSSDBG_CRIT_FAILURE, "Unknown domain: %s\n", domainname); ++ /* domain might be skipped by 'ad_enabled_domains' option */ ++ DEBUG(SSSDBG_CONF_SETTINGS, "Unknown domain: %s\n", domainname); + return ERR_DOMAIN_NOT_FOUND; + } + } diff --git a/SOURCES/0009-SSS_CLIENT-MC-in-case-mem-cache-file-validation-fails.patch b/SOURCES/0009-SSS_CLIENT-MC-in-case-mem-cache-file-validation-fails.patch new file mode 100644 index 0000000..ce8f4c6 --- /dev/null +++ b/SOURCES/0009-SSS_CLIENT-MC-in-case-mem-cache-file-validation-fails.patch @@ -0,0 +1,44 @@ +From 958a5e25c447dc502e8f8fbecf3253e62f92b0b2 Mon Sep 17 00:00:00 2001 +From: Alexey Tikhonov +Date: Fri, 8 Dec 2023 19:02:24 +0100 +Subject: [PATCH] SSS_CLIENT: MC: in case mem-cache file validation fails, +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +don't return anything but EINVAL, because `_nss_sss_*()` functions +can have a special handling for other error codes (for ERANGE in +particular). + +Reviewed-by: Alejandro López +Reviewed-by: Sumit Bose +Reviewed-by: Tomáš Halman +--- + src/sss_client/nss_mc_common.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/sss_client/nss_mc_common.c b/src/sss_client/nss_mc_common.c +index e227c0bae3..37119fa8d3 100644 +--- a/src/sss_client/nss_mc_common.c ++++ b/src/sss_client/nss_mc_common.c +@@ -79,17 +79,17 @@ static errno_t sss_nss_mc_validate(struct sss_cli_mc_ctx *ctx) + } + + if (fstat(ctx->fd, &fdstat) == -1) { +- return errno; ++ return EINVAL; + } + + /* Memcache was removed. */ + if (fdstat.st_nlink == 0) { +- return ENOENT; ++ return EINVAL; + } + + /* Invalid size. */ + if (fdstat.st_size != ctx->mmap_size) { +- return ERANGE; ++ return EINVAL; + } + + return EOK; diff --git a/SOURCES/0010-SSS_CLIENT-check-if-mem-cache-fd-was-hijacked.patch b/SOURCES/0010-SSS_CLIENT-check-if-mem-cache-fd-was-hijacked.patch new file mode 100644 index 0000000..0f363db --- /dev/null +++ b/SOURCES/0010-SSS_CLIENT-check-if-mem-cache-fd-was-hijacked.patch @@ -0,0 +1,82 @@ +From 0344c41aca0d6fcaa33e081ed77297607e48ced4 Mon Sep 17 00:00:00 2001 +From: Alexey Tikhonov +Date: Fri, 15 Dec 2023 14:52:51 +0100 +Subject: [PATCH] SSS_CLIENT: check if mem-cache fd was hijacked +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Real life example would be: +https://github.com/TigerVNC/tigervnc/blob/effd854bfd19654fa67ff3d39514a91a246b8ae6/unix/xserver/hw/vnc/xvnc.c#L369 + - TigerVNC unconditionally overwrites fd=3 + +Resolves: https://github.com/SSSD/sssd/issues/6986 + +Reviewed-by: Alejandro López +Reviewed-by: Sumit Bose +Reviewed-by: Tomáš Halman +--- + src/sss_client/nss_mc.h | 6 ++++-- + src/sss_client/nss_mc_common.c | 10 ++++++++++ + 2 files changed, 14 insertions(+), 2 deletions(-) + +diff --git a/src/sss_client/nss_mc.h b/src/sss_client/nss_mc.h +index 9ab2736fa6..646861ba52 100644 +--- a/src/sss_client/nss_mc.h ++++ b/src/sss_client/nss_mc.h +@@ -53,6 +53,8 @@ struct sss_cli_mc_ctx { + pthread_mutex_t *mutex; + #endif + int fd; ++ ino_t fd_inode; ++ dev_t fd_device; + + uint32_t seed; /* seed from the tables header */ + +@@ -69,9 +71,9 @@ struct sss_cli_mc_ctx { + }; + + #if HAVE_PTHREAD +-#define SSS_CLI_MC_CTX_INITIALIZER(mtx) {UNINITIALIZED, (mtx), -1, 0, NULL, 0, NULL, 0, NULL, 0, 0} ++#define SSS_CLI_MC_CTX_INITIALIZER(mtx) {UNINITIALIZED, (mtx), -1, 0, 0, 0, NULL, 0, NULL, 0, NULL, 0, 0} + #else +-#define SSS_CLI_MC_CTX_INITIALIZER {UNINITIALIZED, -1, 0, NULL, 0, NULL, 0, NULL, 0, 0} ++#define SSS_CLI_MC_CTX_INITIALIZER {UNINITIALIZED, -1, 0, 0, 0, NULL, 0, NULL, 0, NULL, 0, 0} + #endif + + errno_t sss_nss_mc_get_ctx(const char *name, struct sss_cli_mc_ctx *ctx); +diff --git a/src/sss_client/nss_mc_common.c b/src/sss_client/nss_mc_common.c +index 37119fa8d3..17683ac0e5 100644 +--- a/src/sss_client/nss_mc_common.c ++++ b/src/sss_client/nss_mc_common.c +@@ -87,6 +87,12 @@ static errno_t sss_nss_mc_validate(struct sss_cli_mc_ctx *ctx) + return EINVAL; + } + ++ /* FD was hijacked */ ++ if ((fdstat.st_dev != ctx->fd_device) || (fdstat.st_ino != ctx->fd_inode)) { ++ ctx->fd = -1; /* don't ruin app even if it's misbehaving */ ++ return EINVAL; ++ } ++ + /* Invalid size. */ + if (fdstat.st_size != ctx->mmap_size) { + return EINVAL; +@@ -161,6 +167,8 @@ static void sss_nss_mc_destroy_ctx(struct sss_cli_mc_ctx *ctx) + close(ctx->fd); + } + ctx->fd = -1; ++ ctx->fd_inode = 0; ++ ctx->fd_device = 0; + + ctx->seed = 0; + ctx->data_table = NULL; +@@ -202,6 +210,8 @@ static errno_t sss_nss_mc_init_ctx(const char *name, + ret = EIO; + goto done; + } ++ ctx->fd_inode = fdstat.st_ino; ++ ctx->fd_device = fdstat.st_dev; + + if (fdstat.st_size < MC_HEADER_SIZE) { + ret = ENOMEM; diff --git a/SOURCES/0011-SSS_CLIENT-check-if-reponder-socket-was-hijacked.patch b/SOURCES/0011-SSS_CLIENT-check-if-reponder-socket-was-hijacked.patch new file mode 100644 index 0000000..7a4e70e --- /dev/null +++ b/SOURCES/0011-SSS_CLIENT-check-if-reponder-socket-was-hijacked.patch @@ -0,0 +1,40 @@ +From 2bcfb7f9238c27025e99e6445e9ba799e0bde7b8 Mon Sep 17 00:00:00 2001 +From: Alexey Tikhonov +Date: Wed, 20 Dec 2023 09:43:48 +0100 +Subject: [PATCH] SSS_CLIENT: check if reponder socket was hijacked +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Real life example would be: +https://github.com/TigerVNC/tigervnc/blob/effd854bfd19654fa67ff3d39514a91a246b8ae6/unix/xserver/hw/vnc/xvnc.c#L369 + - TigerVNC unconditionally overwrites fd=3 + +Reviewed-by: Alejandro López +Reviewed-by: Sumit Bose +Reviewed-by: Tomáš Halman +--- + src/sss_client/common.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/src/sss_client/common.c b/src/sss_client/common.c +index 07976fbdcd..630f4798fe 100644 +--- a/src/sss_client/common.c ++++ b/src/sss_client/common.c +@@ -767,6 +767,16 @@ static enum sss_status sss_cli_check_socket(int *errnop, + myself_ino = myself_sb.st_ino; + } + ++ /* check if the socket has been hijacked */ ++ if (sss_cli_sd_get() != -1) { ++ ret = fstat(sss_cli_sd_get(), &mypid_sb); ++ if ((ret != 0) || (!S_ISSOCK(mypid_sb.st_mode)) ++ || (mypid_sb.st_dev != sss_cli_sb->st_dev) ++ || (mypid_sb.st_ino != sss_cli_sb->st_ino)) { ++ sss_cli_sd_set(-1); /* don't ruin app even if it's misbehaving */ ++ } ++ } ++ + /* check if the socket has been closed on the other side */ + if (sss_cli_sd_get() != -1) { + struct pollfd pfd; diff --git a/SOURCES/0012-LDAP-make-groups_by_user_send-recv-public.patch b/SOURCES/0012-LDAP-make-groups_by_user_send-recv-public.patch new file mode 100644 index 0000000..766c495 --- /dev/null +++ b/SOURCES/0012-LDAP-make-groups_by_user_send-recv-public.patch @@ -0,0 +1,69 @@ +From 9b73614c49aeb3cfc3208dba5f472354086180b5 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Fri, 3 Nov 2023 18:43:13 +0100 +Subject: [PATCH] LDAP: make groups_by_user_send/recv public +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Resolves: https://github.com/SSSD/sssd/issues/5708 + +Reviewed-by: Justin Stephenson +Reviewed-by: Tomáš Halman +--- + src/providers/ldap/ldap_common.h | 12 ++++++++++++ + src/providers/ldap/ldap_id.c | 18 +++++++++--------- + 2 files changed, 21 insertions(+), 9 deletions(-) + +diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h +index 1b35cbd208..6df7b3df44 100644 +--- a/src/providers/ldap/ldap_common.h ++++ b/src/providers/ldap/ldap_common.h +@@ -298,6 +298,18 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx, + bool no_members); + int groups_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret); + ++struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx, ++ struct tevent_context *ev, ++ struct sdap_id_ctx *ctx, ++ struct sdap_domain *sdom, ++ struct sdap_id_conn_ctx *conn, ++ const char *filter_value, ++ int filter_type, ++ const char *extra_value, ++ bool noexist_delete); ++ ++int groups_by_user_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret); ++ + struct tevent_req *ldap_netgroup_get_send(TALLOC_CTX *memctx, + struct tevent_context *ev, + struct sdap_id_ctx *ctx, +diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c +index a60aed0686..fb81a17937 100644 +--- a/src/providers/ldap/ldap_id.c ++++ b/src/providers/ldap/ldap_id.c +@@ -1151,15 +1151,15 @@ static int groups_by_user_retry(struct tevent_req *req); + static void groups_by_user_connect_done(struct tevent_req *subreq); + static void groups_by_user_done(struct tevent_req *subreq); + +-static struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx, +- struct tevent_context *ev, +- struct sdap_id_ctx *ctx, +- struct sdap_domain *sdom, +- struct sdap_id_conn_ctx *conn, +- const char *filter_value, +- int filter_type, +- const char *extra_value, +- bool noexist_delete) ++struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx, ++ struct tevent_context *ev, ++ struct sdap_id_ctx *ctx, ++ struct sdap_domain *sdom, ++ struct sdap_id_conn_ctx *conn, ++ const char *filter_value, ++ int filter_type, ++ const char *extra_value, ++ bool noexist_delete) + { + struct tevent_req *req; + struct groups_by_user_state *state; diff --git a/SOURCES/0013-ad-gpo-evalute-host-groups.patch b/SOURCES/0013-ad-gpo-evalute-host-groups.patch new file mode 100644 index 0000000..145c156 --- /dev/null +++ b/SOURCES/0013-ad-gpo-evalute-host-groups.patch @@ -0,0 +1,623 @@ +From c02e09afe9610d872121708893db8a21fb201b12 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Mon, 6 Nov 2023 18:17:28 +0100 +Subject: [PATCH] ad: gpo evalute host groups +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +With this patch the group-memberships of the client running SSSD are +included in the evaluation of the security filtering. Similar as in AD +the host object is more or less handled as a user object which allows +to skip some code dedicated to computers only. + +Resolves: https://github.com/SSSD/sssd/issues/5708 + +Reviewed-by: Justin Stephenson +Reviewed-by: Tomáš Halman +--- + src/providers/ad/ad_gpo.c | 332 +++++++++++---------------------- + src/tests/cmocka/test_ad_gpo.c | 25 ++- + 2 files changed, 134 insertions(+), 223 deletions(-) + +diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c +index b119aa3776..1c731b222b 100644 +--- a/src/providers/ad/ad_gpo.c ++++ b/src/providers/ad/ad_gpo.c +@@ -661,6 +661,8 @@ ad_gpo_ace_includes_client_sid(const char *user_sid, + const char *host_sid, + const char **group_sids, + int group_size, ++ const char **host_group_sids, ++ int host_group_size, + struct dom_sid ace_dom_sid, + struct sss_idmap_ctx *idmap_ctx, + bool *_included) +@@ -718,6 +720,22 @@ ad_gpo_ace_includes_client_sid(const char *user_sid, + } + } + ++ for (i = 0; i < host_group_size; i++) { ++ err = sss_idmap_sid_to_smb_sid(idmap_ctx, host_group_sids[i], &group_dom_sid); ++ if (err != IDMAP_SUCCESS) { ++ 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); ++ sss_idmap_free_smb_sid(idmap_ctx, group_dom_sid); ++ if (included) { ++ *_included = true; ++ return EOK; ++ } ++ } ++ + *_included = false; + return EOK; + } +@@ -770,7 +788,9 @@ static enum ace_eval_agp_status ad_gpo_evaluate_ace(struct security_ace *ace, + const char *user_sid, + const char *host_sid, + const char **group_sids, +- int group_size) ++ int group_size, ++ const char **host_group_sids, ++ int host_group_size) + { + bool included = false; + int ret = 0; +@@ -782,9 +802,9 @@ static enum ace_eval_agp_status ad_gpo_evaluate_ace(struct security_ace *ace, + } + + ret = ad_gpo_ace_includes_client_sid(user_sid, host_sid, group_sids, +- group_size, ace->trustee, idmap_ctx, +- &included); +- ++ group_size, host_group_sids, ++ host_group_size, ace->trustee, ++ idmap_ctx, &included); + if (ret != EOK) { + return AD_GPO_ACE_DENIED; + } +@@ -844,6 +864,8 @@ static errno_t ad_gpo_simple_evaluate_ace(struct security_ace *ace, + const char *host_sid, + const char **group_sids, + int group_size, ++ const char **host_group_sids, ++ int host_group_size, + uint32_t *_gpo_access_granted_status, + uint32_t *_gpo_access_denied_status) + { +@@ -856,6 +878,7 @@ static errno_t ad_gpo_simple_evaluate_ace(struct security_ace *ace, + } + + ret = ad_gpo_ace_includes_client_sid(user_sid, host_sid, group_sids, group_size, ++ host_group_sids, host_group_size, + ace->trustee, idmap_ctx, &included); + + if (ret != EOK || !included) { +@@ -895,6 +918,8 @@ static errno_t ad_gpo_evaluate_dacl(struct security_acl *dacl, + const char *host_sid, + const char **group_sids, + int group_size, ++ const char **host_group_sids, ++ int host_group_size, + bool *_dacl_access_allowed) + { + uint32_t num_aces = 0; +@@ -931,6 +956,7 @@ static errno_t ad_gpo_evaluate_dacl(struct security_acl *dacl, + + ret = ad_gpo_simple_evaluate_ace(ace, idmap_ctx, user_sid, host_sid, + group_sids, group_size, ++ host_group_sids, host_group_size, + &access_granted_status, + &access_denied_status); + +@@ -963,7 +989,8 @@ static errno_t ad_gpo_evaluate_dacl(struct security_acl *dacl, + } + + ace_status = ad_gpo_evaluate_ace(ace, idmap_ctx, user_sid, host_sid, +- group_sids, group_size); ++ group_sids, group_size, ++ host_group_sids, host_group_size); + + switch (ace_status) { + case AD_GPO_ACE_NEUTRAL: +@@ -1016,8 +1043,9 @@ static errno_t ad_gpo_evaluate_dacl(struct security_acl *dacl, + static errno_t + ad_gpo_filter_gpos_by_dacl(TALLOC_CTX *mem_ctx, + const char *user, +- const char *host_sid, ++ const char *host_fqdn, + struct sss_domain_info *domain, ++ struct sss_domain_info *host_domain, + struct sss_idmap_ctx *idmap_ctx, + struct gp_gpo **candidate_gpos, + int num_candidate_gpos, +@@ -1033,6 +1061,9 @@ ad_gpo_filter_gpos_by_dacl(TALLOC_CTX *mem_ctx, + const char *user_sid = NULL; + const char **group_sids = NULL; + int group_size = 0; ++ const char *host_sid = NULL; ++ const char **host_group_sids = NULL; ++ int host_group_size = 0; + int gpo_dn_idx = 0; + bool access_allowed = false; + struct gp_gpo **dacl_filtered_gpos = NULL; +@@ -1052,6 +1083,15 @@ ad_gpo_filter_gpos_by_dacl(TALLOC_CTX *mem_ctx, + goto done; + } + ++ ret = ad_gpo_get_sids(tmp_ctx, host_fqdn, host_domain, &host_sid, ++ &host_group_sids, &host_group_size); ++ if (ret != EOK) { ++ ret = ERR_NO_SIDS; ++ DEBUG(SSSDBG_OP_FAILURE, ++ "Unable to retrieve host SIDs: [%d](%s)\n", ret, sss_strerror(ret)); ++ goto done; ++ } ++ + dacl_filtered_gpos = talloc_array(tmp_ctx, + struct gp_gpo *, + num_candidate_gpos + 1); +@@ -1096,7 +1136,8 @@ ad_gpo_filter_gpos_by_dacl(TALLOC_CTX *mem_ctx, + + if ((sd->type & SEC_DESC_DACL_PRESENT) && (dacl != NULL)) { + ret = ad_gpo_evaluate_dacl(dacl, idmap_ctx, user_sid, host_sid, +- group_sids, group_size, &access_allowed); ++ group_sids, group_size, host_group_sids, ++ host_group_size, &access_allowed); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, + "Could not determine if GPO is applicable\n"); +@@ -1773,6 +1814,8 @@ struct ad_gpo_access_state { + int timeout; + struct sss_domain_info *user_domain; + struct sss_domain_info *host_domain; ++ const char *host_sam_account_name; ++ char *host_fqdn; + const char *user; + int gpo_timeout_option; + const char *ad_hostname; +@@ -1793,7 +1836,6 @@ static void ad_gpo_process_gpo_done(struct tevent_req *subreq); + + static errno_t ad_gpo_cse_step(struct tevent_req *req); + static void ad_gpo_cse_done(struct tevent_req *subreq); +-static void ad_gpo_get_host_sid_retrieval_done(struct tevent_req *subreq); + + struct tevent_req * + ad_gpo_access_send(TALLOC_CTX *mem_ctx, +@@ -1967,15 +2009,11 @@ ad_gpo_connect_done(struct tevent_req *subreq) + { + struct tevent_req *req; + struct ad_gpo_access_state *state; +- char *filter; +- const char *sam_account_name; +- char *domain_dn; + int dp_error; + errno_t ret; + char *server_uri; + LDAPURLDesc *lud; +- +- const char *attrs[] = {AD_AT_DN, AD_AT_UAC, NULL}; ++ struct sdap_domain *sdom; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct ad_gpo_access_state); +@@ -2041,47 +2079,40 @@ ad_gpo_connect_done(struct tevent_req *subreq) + + /* SDAP_SASL_AUTHID contains the name used for kinit and SASL bind which + * in the AD case is the NetBIOS name. */ +- sam_account_name = dp_opt_get_string(state->opts->basic, SDAP_SASL_AUTHID); +- if (sam_account_name == NULL) { ++ state->host_sam_account_name = dp_opt_get_string(state->opts->basic, ++ SDAP_SASL_AUTHID); ++ if (state->host_sam_account_name == NULL) { + ret = ENOMEM; + goto done; + } + +- DEBUG(SSSDBG_TRACE_FUNC, "sam_account_name is %s\n", sam_account_name); ++ DEBUG(SSSDBG_TRACE_FUNC, "sam_account_name is %s\n", ++ state->host_sam_account_name); + +- /* Convert the domain name into domain DN */ +- ret = domain_to_basedn(state, state->ad_domain, &domain_dn); +- if (ret != EOK) { ++ state->host_fqdn = sss_create_internal_fqname(state, state->host_sam_account_name, ++ state->host_domain->name); ++ if (state->host_fqdn == NULL) { + DEBUG(SSSDBG_OP_FAILURE, +- "Cannot convert domain name [%s] to base DN [%d]: %s\n", +- state->ad_domain, ret, sss_strerror(ret)); +- goto done; +- } +- +- /* SDAP_OC_USER objectclass covers both users and computers */ +- filter = talloc_asprintf(state, +- "(&(objectclass=%s)(%s=%s))", +- state->opts->user_map[SDAP_OC_USER].name, +- AD_AT_SAMACCOUNTNAME, +- sam_account_name); +- if (filter == NULL) { ++ "Failed to create fully-qualified host name.\n"); + ret = ENOMEM; + goto done; + } + +- subreq = sdap_get_generic_send(state, state->ev, state->opts, +- sdap_id_op_handle(state->sdap_op), +- domain_dn, LDAP_SCOPE_SUBTREE, +- filter, attrs, NULL, 0, +- state->timeout, +- false); +- +- if (subreq == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, "sdap_get_generic_send failed.\n"); ++ /* AD handle computers the same as users */ ++ sdom = sdap_domain_get(state->access_ctx->ad_id_ctx->sdap_id_ctx->opts, ++ state->host_domain); ++ if (sdom == NULL) { + ret = EIO; + goto done; + } + ++ subreq = groups_by_user_send(state, state->ev, ++ state->access_ctx->ad_id_ctx->sdap_id_ctx, ++ sdom, state->conn, ++ state->host_fqdn, ++ BE_FILTER_NAME, ++ NULL, ++ true); + tevent_req_set_callback(subreq, ad_gpo_target_dn_retrieval_done, req); + + ret = EOK; +@@ -2100,22 +2131,20 @@ ad_gpo_target_dn_retrieval_done(struct tevent_req *subreq) + struct ad_gpo_access_state *state; + int ret; + int dp_error; +- size_t reply_count; +- struct sysdb_attrs **reply; ++ int sdap_ret; + const char *target_dn = NULL; + uint32_t uac; +- const char *attrs[] = {AD_AT_SID, NULL}; +- struct ldb_message *msg; +- static const char *host_attrs[] = { SYSDB_SID_STR, NULL }; ++ static const char *host_attrs[] = { SYSDB_ORIG_DN, SYSDB_AD_USER_ACCOUNT_CONTROL, SYSDB_SID_STR, NULL }; ++ struct ldb_result *res = NULL; ++ const char *tmp = NULL; ++ char *endptr; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct ad_gpo_access_state); +- ret = sdap_get_generic_recv(subreq, state, +- &reply_count, &reply); ++ ret = groups_by_user_recv(subreq, &dp_error, &sdap_ret); + talloc_zfree(subreq); + if (ret != EOK) { +- ret = sdap_id_op_done(state->sdap_op, ret, &dp_error); +- if (ret == EAGAIN && dp_error == DP_ERR_OFFLINE) { ++ if (sdap_ret == EAGAIN && dp_error == DP_ERR_OFFLINE) { + DEBUG(SSSDBG_TRACE_FUNC, "Preparing for offline operation.\n"); + ret = process_offline_gpos(state, + state->user, +@@ -2144,27 +2173,25 @@ ad_gpo_target_dn_retrieval_done(struct tevent_req *subreq) + goto done; + } + +- /* make sure there is only one non-NULL reply returned */ +- +- if (reply_count < 1) { +- DEBUG(SSSDBG_OP_FAILURE, "No DN retrieved for policy target.\n"); +- ret = ENOENT; +- goto done; +- } else if (reply_count > 1) { +- DEBUG(SSSDBG_OP_FAILURE, "Multiple replies for policy target\n"); +- ret = ERR_INTERNAL; ++ ret = sysdb_get_user_attr(state, state->host_domain, ++ state->host_fqdn, ++ host_attrs, &res); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, "Failed to read host attributes.\n"); + goto done; +- } else if (reply == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, "reply_count is 1, but reply is NULL\n"); +- ret = ERR_INTERNAL; ++ } ++ if (res->count != 1) { ++ DEBUG(SSSDBG_OP_FAILURE, "Unexpected number [%d] of results searching " ++ "for [%s], expected 1.\n", res->count, ++ state->host_sam_account_name); ++ ret = EINVAL; + goto done; + } + +- /* reply[0] holds requested attributes of single reply */ +- ret = sysdb_attrs_get_string(reply[0], AD_AT_DN, &target_dn); +- if (ret != EOK) { ++ target_dn = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_ORIG_DN, NULL); ++ if (target_dn == NULL) { + DEBUG(SSSDBG_OP_FAILURE, +- "sysdb_attrs_get_string failed: [%d](%s)\n", ++ "ldb_msg_find_attr_as_string failed: [%d](%s)\n", + ret, sss_strerror(ret)); + goto done; + } +@@ -2174,14 +2201,29 @@ ad_gpo_target_dn_retrieval_done(struct tevent_req *subreq) + goto done; + } + +- ret = sysdb_attrs_get_uint32_t(reply[0], AD_AT_UAC, &uac); +- if (ret != EOK) { ++ tmp = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_AD_USER_ACCOUNT_CONTROL, ++ NULL); ++ if (tmp == NULL) { + DEBUG(SSSDBG_OP_FAILURE, +- "sysdb_attrs_get_uint32_t failed: [%d](%s)\n", ++ "ldb_msg_find_attr_as_string failed: [%d](%s)\n", + ret, sss_strerror(ret)); + goto done; + } + ++ uac = strtouint32(tmp, &endptr, 10); ++ if (errno != 0) { ++ ret = errno; ++ DEBUG(SSSDBG_OP_FAILURE, "Failed to convert UAC [%s] into uint32_t.\n", ++ tmp); ++ goto done; ++ } ++ if (*endptr != '\0') { ++ ret = EINVAL; ++ DEBUG(SSSDBG_OP_FAILURE, "UAC [%s] is not a pure numerical value.\n", ++ tmp); ++ goto done; ++ } ++ + /* we only support computer policy targets, not users */ + if (!(uac & UAC_WORKSTATION_TRUST_ACCOUNT || + uac & UAC_SERVER_TRUST_ACCOUNT)) { +@@ -2192,36 +2234,8 @@ ad_gpo_target_dn_retrieval_done(struct tevent_req *subreq) + goto done; + } + +- /* Check if computer exists in cache */ +- ret = sysdb_get_computer(state, state->user_domain, state->ad_hostname, +- host_attrs, &msg); +- if (ret == ENOENT) { +- /* The computer is not in cache so query LDAP server */ +- subreq = sdap_get_generic_send(state, state->ev, state->opts, +- sdap_id_op_handle(state->sdap_op), +- state->target_dn, LDAP_SCOPE_BASE, +- "(&)", attrs, NULL, 0, +- state->timeout, +- false); +- +- if (subreq == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, "sdap_get_generic_send failed.\n"); +- ret = ENOMEM; +- goto done; +- } +- +- tevent_req_set_callback(subreq, ad_gpo_get_host_sid_retrieval_done, req); +- return; +- } else if (ret != EOK) { +- ret = sdap_id_op_done(state->sdap_op, ret, &dp_error); +- goto done; +- } +- +- /* The computer exists in the cache, there is no need to query LDAP. +- * Store the retrieved host sid from cache in the state to avoid querying +- * the cache again in ad_gpo_get_sids. +- */ +- state->host_sid = ldb_msg_find_attr_as_string(msg, SYSDB_SID_STR, NULL); ++ state->host_sid = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_SID_STR, ++ NULL); + talloc_steal(state, state->host_sid); + + subreq = ad_gpo_process_som_send(state, +@@ -2251,125 +2265,6 @@ ad_gpo_target_dn_retrieval_done(struct tevent_req *subreq) + + } + +-enum ndr_err_code +-ndr_pull_dom_sid(struct ndr_pull *ndr, +- int ndr_flags, +- struct dom_sid *r); +- +-static void ad_gpo_get_host_sid_retrieval_done(struct tevent_req *subreq) +-{ +- struct tevent_req *req; +- struct ad_gpo_access_state *state; +- int ret; +- int dp_error; +- size_t reply_count; +- struct sysdb_attrs **reply; +- struct ldb_message_element *el = NULL; +- enum ndr_err_code ndr_err; +- struct dom_sid host_sid; +- char *sid_str; +- +- req = tevent_req_callback_data(subreq, struct tevent_req); +- state = tevent_req_data(req, struct ad_gpo_access_state); +- +- ret = sdap_get_generic_recv(subreq, state, +- &reply_count, &reply); +- talloc_zfree(subreq); +- +- if (ret != EOK) { +- ret = sdap_id_op_done(state->sdap_op, ret, &dp_error); +- +- DEBUG(SSSDBG_OP_FAILURE, +- "sdap_get_generic_recv failed: [%d](%s)\n", +- ret, sss_strerror(ret)); +- ret = ENOENT; +- tevent_req_error(req, ret); +- return; +- } +- +- if (reply_count == 0 || !reply) { +- DEBUG(SSSDBG_OP_FAILURE, +- "sdap_get_generic_recv failed to receive host sid\n"); +- ret = EIO; +- goto done; +- } +- +- /* reply[0] holds the requested attribute */ +- ret = sysdb_attrs_get_el(reply[0], AD_AT_SID, &el); +- if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, +- "sysdb_attrs_get_el failed: [%d](%s)\n", +- ret, sss_strerror(ret)); +- goto done; +- } +- if (el->num_values != 1) { +- DEBUG(SSSDBG_OP_FAILURE, +- "ad_gpo_get_host_sid_retrieval_done failed: sid not present\n"); +- ret = EIO; +- goto done; +- } +- +- /* parse the dom_sid from the ldb blob */ +- ndr_err = ndr_pull_struct_blob_all((DATA_BLOB*)&(el->values[0]), +- subreq, &host_sid, +- (ndr_pull_flags_fn_t)ndr_pull_dom_sid); +- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { +- DEBUG(SSSDBG_OP_FAILURE, +- "ndr_pull_struct_blob_all failed: [%d]\n", +- ndr_err); +- ret = EIO; +- goto done; +- } +- +- /* Convert the dom_sid to a sid string */ +- ret = sss_idmap_smb_sid_to_sid(state->opts->idmap_ctx->map, +- &host_sid, &sid_str); +- if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, +- "sss_idmap_smb_sid_to_sid failed: [%d](%s)\n", +- ret, sss_strerror(ret)); +- goto done; +- } +- state->host_sid = talloc_steal(state, sid_str); +- +- /* Put the sid string in the sysdb */ +- ret = sysdb_set_computer(subreq, state->user_domain, +- state->ad_hostname, state->host_sid, +- state->user_domain->computer_timeout, +- time(NULL)); +- if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, +- "sysdb_set_computer failed: [%d](%s)\n", +- ret, sss_strerror(ret)); +- goto done; +- } +- +- subreq = ad_gpo_process_som_send(state, +- state->ev, +- state->conn, +- state->ldb_ctx, +- state->sdap_op, +- state->opts, +- state->access_ctx->ad_options, +- state->timeout, +- state->target_dn, +- state->ad_domain); +- if (subreq == NULL) { +- ret = ENOMEM; +- goto done; +- } +- +- tevent_req_set_callback(subreq, ad_gpo_process_som_done, req); +- +- ret = EOK; +- +- done: +- +- if (ret != EOK) { +- tevent_req_error(req, ret); +- } +-} +- + static void + ad_gpo_process_som_done(struct tevent_req *subreq) + { +@@ -2487,8 +2382,9 @@ ad_gpo_process_gpo_done(struct tevent_req *subreq) + goto done; + } + +- ret = ad_gpo_filter_gpos_by_dacl(state, state->user, state->host_sid, ++ ret = ad_gpo_filter_gpos_by_dacl(state, state->user, state->host_fqdn, + state->user_domain, ++ state->host_domain, + state->opts->idmap_ctx->map, + candidate_gpos, num_candidate_gpos, + &state->dacl_filtered_gpos, +diff --git a/src/tests/cmocka/test_ad_gpo.c b/src/tests/cmocka/test_ad_gpo.c +index 8660b05107..d49f6c54c2 100644 +--- a/src/tests/cmocka/test_ad_gpo.c ++++ b/src/tests/cmocka/test_ad_gpo.c +@@ -270,6 +270,8 @@ static void test_ad_gpo_ace_includes_client_sid(const char *user_sid, + const char *host_sid, + const char **group_sids, + int group_size, ++ const char **host_group_sids, ++ int host_group_size, + struct dom_sid ace_dom_sid, + bool expected) + { +@@ -288,8 +290,9 @@ static void test_ad_gpo_ace_includes_client_sid(const char *user_sid, + assert_int_equal(err, IDMAP_SUCCESS); + + ret = ad_gpo_ace_includes_client_sid(user_sid, host_sid, group_sids, +- group_size, ace_dom_sid, idmap_ctx, +- &includes_client_sid); ++ group_size, host_group_sids, ++ host_group_size, ace_dom_sid, ++ idmap_ctx, &includes_client_sid); + talloc_free(idmap_ctx); + + assert_int_equal(ret, EOK); +@@ -312,8 +315,12 @@ void test_ad_gpo_ace_includes_client_sid_true(void **state) + const char *group_sids[] = {"S-1-5-21-2-3-4", + "S-1-5-21-2-3-5"}; + ++ int host_group_size = 0; ++ const char *host_group_sids[] = { NULL }; ++ + test_ad_gpo_ace_includes_client_sid(user_sid, host_sid, group_sids, +- group_size, ace_dom_sid, true); ++ group_size, host_group_sids, ++ host_group_size, ace_dom_sid, true); + } + + void test_ad_gpo_ace_includes_client_sid_false(void **state) +@@ -328,8 +335,12 @@ void test_ad_gpo_ace_includes_client_sid_false(void **state) + const char *group_sids[] = {"S-1-5-21-2-3-5", + "S-1-5-21-2-3-6"}; + ++ int host_group_size = 0; ++ const char *host_group_sids[] = { NULL }; ++ + test_ad_gpo_ace_includes_client_sid(user_sid, host_sid, group_sids, +- group_size, ace_dom_sid, false); ++ group_size, host_group_sids, ++ host_group_size, ace_dom_sid, false); + } + + void test_ad_gpo_ace_includes_host_sid_true(void **state) +@@ -343,8 +354,12 @@ void test_ad_gpo_ace_includes_host_sid_true(void **state) + int group_size = 0; + const char *group_sids[] = {}; + ++ int host_group_size = 0; ++ const char *host_group_sids[] = { NULL }; ++ + test_ad_gpo_ace_includes_client_sid(user_sid, host_sid, group_sids, +- group_size, ace_dom_sid, true); ++ group_size, host_group_sids, ++ host_group_size, ace_dom_sid, true); + } + + uint8_t test_sid_data[] = { diff --git a/SOURCES/0014-sysdb-remove-sysdb_computer.ch.patch b/SOURCES/0014-sysdb-remove-sysdb_computer.ch.patch new file mode 100644 index 0000000..8132744 --- /dev/null +++ b/SOURCES/0014-sysdb-remove-sysdb_computer.ch.patch @@ -0,0 +1,303 @@ +From ff23e7e2879f94a907d05b615dbdb547aaa2e542 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Fri, 17 Nov 2023 19:09:05 +0100 +Subject: [PATCH] sysdb: remove sysdb_computer.[ch] +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The related calls are not needed anymore. + +Resolves: https://github.com/SSSD/sssd/issues/5708 + +Reviewed-by: Justin Stephenson +Reviewed-by: Tomáš Halman +--- + Makefile.am | 2 - + src/db/sysdb_computer.c | 185 -------------------------------------- + src/db/sysdb_computer.h | 51 ----------- + src/providers/ad/ad_gpo.c | 1 - + 4 files changed, 239 deletions(-) + delete mode 100644 src/db/sysdb_computer.c + delete mode 100644 src/db/sysdb_computer.h + +diff --git a/Makefile.am b/Makefile.am +index ead2bf7c0b..7ec14fc476 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -812,7 +812,6 @@ dist_noinst_HEADERS = \ + src/db/sysdb_subid.h \ + src/db/sysdb_domain_resolution_order.h \ + src/db/sysdb_passkey_user_verification.h \ +- src/db/sysdb_computer.h \ + src/db/sysdb_iphosts.h \ + src/db/sysdb_ipnetworks.h \ + src/confdb/confdb.h \ +@@ -1252,7 +1251,6 @@ libsss_util_la_SOURCES = \ + src/db/sysdb_iphosts.c \ + src/db/sysdb_ipnetworks.c \ + src/util/sss_pam_data.c \ +- src/db/sysdb_computer.c \ + src/db/sysdb_subid.c \ + src/util/util.c \ + src/util/util_ext.c \ +diff --git a/src/db/sysdb_computer.c b/src/db/sysdb_computer.c +deleted file mode 100644 +index 9fcaf5a7c3..0000000000 +--- a/src/db/sysdb_computer.c ++++ /dev/null +@@ -1,185 +0,0 @@ +-/* +- SSSD +- +- Authors: +- Samuel Cabrero +- David Mulder +- +- Copyright (C) 2019 SUSE LINUX GmbH, Nuernberg, Germany. +- +- 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 "db/sysdb.h" +-#include "db/sysdb_private.h" +-#include "db/sysdb_computer.h" +- +-static errno_t +-sysdb_search_computer(TALLOC_CTX *mem_ctx, +- struct sss_domain_info *domain, +- const char *filter, +- const char **attrs, +- size_t *_num_hosts, +- struct ldb_message ***_hosts) +-{ +- errno_t ret; +- TALLOC_CTX *tmp_ctx; +- struct ldb_message **results; +- size_t num_results; +- +- tmp_ctx = talloc_new(NULL); +- if (!tmp_ctx) { +- return ENOMEM; +- } +- +- ret = sysdb_search_custom(tmp_ctx, domain, filter, +- COMPUTERS_SUBDIR, attrs, +- &num_results, &results); +- if (ret != EOK && ret != ENOENT) { +- DEBUG(SSSDBG_CRIT_FAILURE, +- "Error looking up host [%d]: %s\n", +- ret, strerror(ret)); +- goto done; +- } else if (ret == ENOENT) { +- DEBUG(SSSDBG_TRACE_FUNC, "No such host\n"); +- *_hosts = NULL; +- *_num_hosts = 0; +- goto done; +- } +- +- *_hosts = talloc_steal(mem_ctx, results); +- *_num_hosts = num_results; +- ret = EOK; +- +-done: +- talloc_free(tmp_ctx); +- +- return ret; +-} +- +-int +-sysdb_get_computer(TALLOC_CTX *mem_ctx, +- struct sss_domain_info *domain, +- const char *computer_name, +- const char **attrs, +- struct ldb_message **_computer) +-{ +- TALLOC_CTX *tmp_ctx; +- errno_t ret; +- const char *filter; +- struct ldb_message **hosts; +- size_t num_hosts; +- +- tmp_ctx = talloc_new(NULL); +- if (!tmp_ctx) { +- return ENOMEM; +- } +- +- filter = talloc_asprintf(tmp_ctx, SYSDB_COMP_FILTER, computer_name); +- if (!filter) { +- ret = ENOMEM; +- goto done; +- } +- +- ret = sysdb_search_computer(tmp_ctx, domain, filter, attrs, +- &num_hosts, &hosts); +- if (ret != EOK) { +- goto done; +- } +- +- if (num_hosts != 1) { +- ret = EINVAL; +- DEBUG(SSSDBG_CRIT_FAILURE, +- "Did not find a single host with name %s\n", computer_name); +- goto done; +- } +- +- *_computer = talloc_steal(mem_ctx, hosts[0]); +- ret = EOK; +- +-done: +- talloc_free(tmp_ctx); +- +- return ret; +-} +- +-int +-sysdb_set_computer(TALLOC_CTX *mem_ctx, +- struct sss_domain_info *domain, +- const char *computer_name, +- const char *sid_str, +- int cache_timeout, +- time_t now) +-{ +- TALLOC_CTX *tmp_ctx; +- int ret; +- struct sysdb_attrs *attrs; +- +- tmp_ctx = talloc_new(NULL); +- if (!tmp_ctx) { +- return ENOMEM; +- } +- +- attrs = sysdb_new_attrs(tmp_ctx); +- if (!attrs) { +- ret = ENOMEM; +- goto done; +- } +- +- ret = sysdb_attrs_add_string(attrs, SYSDB_SID_STR, sid_str); +- if (ret) goto done; +- +- ret = sysdb_attrs_add_string(attrs, SYSDB_OBJECTCLASS, SYSDB_COMPUTER_CLASS); +- if (ret) goto done; +- +- ret = sysdb_attrs_add_string(attrs, SYSDB_NAME, computer_name); +- if (ret) goto done; +- +- /* creation time */ +- ret = sysdb_attrs_add_time_t(attrs, SYSDB_CREATE_TIME, now); +- if (ret) goto done; +- +- /* Set a cache expire time. There is a periodic task that cleans up +- * expired entries from the cache even when enumeration is disabled */ +- ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE, +- cache_timeout ? (now + cache_timeout) : 0); +- if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, "Could not set sysdb cache expire [%d]: %s\n", +- ret, strerror(ret)); +- goto done; +- } +- +- ret = sysdb_store_custom(domain, computer_name, COMPUTERS_SUBDIR, attrs); +- if (ret) goto done; +- +- /* FIXME As a future improvement we have to extend domain enumeration. +- * When 'enumerate = true' for a domain, sssd starts a periodic task +- * that brings all users and groups to the cache, cleaning up +- * stale objects after each run. If enumeration is disabled, the cleanup +- * task for expired entries is started instead. +- * +- * We have to extend the enumeration task to fetch 'computer' +- * objects as well (see ad_id_enumeration_send, the entry point of the +- * enumeration task for the id provider). +- */ +-done: +- if (ret) { +- DEBUG(SSSDBG_TRACE_FUNC, "Error: %d (%s)\n", ret, strerror(ret)); +- } +- talloc_zfree(tmp_ctx); +- +- return ret; +-} +diff --git a/src/db/sysdb_computer.h b/src/db/sysdb_computer.h +deleted file mode 100644 +index 4be67fdf51..0000000000 +--- a/src/db/sysdb_computer.h ++++ /dev/null +@@ -1,51 +0,0 @@ +-/* +- SSSD +- +- Authors: +- Samuel Cabrero +- David Mulder +- +- Copyright (C) 2019 SUSE LINUX GmbH, Nuernberg, Germany. +- +- 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 . +-*/ +- +-#ifndef SYSDB_COMPUTERS_H_ +-#define SYSDB_COMPUTERS_H_ +- +-#include "db/sysdb.h" +- +-#define COMPUTERS_SUBDIR "computers" +-#define SYSDB_COMPUTER_CLASS "computer" +-#define SYSDB_COMPUTERS_CONTAINER "cn="COMPUTERS_SUBDIR +-#define SYSDB_TMPL_COMPUTER_BASE SYSDB_COMPUTERS_CONTAINER","SYSDB_DOM_BASE +-#define SYSDB_TMPL_COMPUTER SYSDB_NAME"=%s,"SYSDB_TMPL_COMPUTER_BASE +-#define SYSDB_COMP_FILTER "(&("SYSDB_NAME"=%s)("SYSDB_OBJECTCLASS"="SYSDB_COMPUTER_CLASS"))" +- +-int +-sysdb_get_computer(TALLOC_CTX *mem_ctx, +- struct sss_domain_info *domain, +- const char *computer_name, +- const char **attrs, +- struct ldb_message **computer); +- +-int +-sysdb_set_computer(TALLOC_CTX *mem_ctx, +- struct sss_domain_info *domain, +- const char *computer_name, +- const char *sid_str, +- int cache_timeout, +- time_t now); +- +-#endif /* SYSDB_COMPUTERS_H_ */ +diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c +index 1c731b222b..f78f17f7b4 100644 +--- a/src/providers/ad/ad_gpo.c ++++ b/src/providers/ad/ad_gpo.c +@@ -53,7 +53,6 @@ + #include "util/sss_chain_id.h" + #include + #include +-#include + + /* == gpo-ldap constants =================================================== */ + diff --git a/SOURCES/0015-sdap-add-set_non_posix-parameter.patch b/SOURCES/0015-sdap-add-set_non_posix-parameter.patch new file mode 100644 index 0000000..e86f8c0 --- /dev/null +++ b/SOURCES/0015-sdap-add-set_non_posix-parameter.patch @@ -0,0 +1,347 @@ +From 5f63d9bfc71b271844db1ee122172630be1afed0 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Tue, 9 Jan 2024 11:14:42 +0100 +Subject: [PATCH] sdap: add set_non_posix parameter +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This patch adds a new parameter set_non_posix to the user and group +lookup calls. Currently the domain type is used to determine if the +search should be restricted to POSIX objects or not. The new option +allows to drop this restriction explicitly to look up non-POSIX objects. + +Resolves: https://github.com/SSSD/sssd/issues/5708 + +Reviewed-by: Justin Stephenson +Reviewed-by: Tomáš Halman +--- + src/providers/ad/ad_gpo.c | 1 + + src/providers/ipa/ipa_subdomains_ext_groups.c | 2 +- + src/providers/ldap/ldap_common.h | 6 ++- + src/providers/ldap/ldap_id.c | 38 +++++++++++-------- + src/providers/ldap/sdap_async.h | 3 +- + src/providers/ldap/sdap_async_initgroups.c | 9 +++-- + src/providers/ldap/sdap_async_initgroups_ad.c | 2 +- + src/providers/ldap/sdap_async_users.c | 9 +++-- + src/providers/ldap/sdap_users.h | 3 +- + 9 files changed, 44 insertions(+), 29 deletions(-) + +diff --git a/src/providers/ad/ad_gpo.c b/src/providers/ad/ad_gpo.c +index f78f17f7b4..336d475d19 100644 +--- a/src/providers/ad/ad_gpo.c ++++ b/src/providers/ad/ad_gpo.c +@@ -2111,6 +2111,7 @@ ad_gpo_connect_done(struct tevent_req *subreq) + state->host_fqdn, + BE_FILTER_NAME, + NULL, ++ true, + true); + tevent_req_set_callback(subreq, ad_gpo_target_dn_retrieval_done, req); + +diff --git a/src/providers/ipa/ipa_subdomains_ext_groups.c b/src/providers/ipa/ipa_subdomains_ext_groups.c +index b385c2f272..f4f84749a2 100644 +--- a/src/providers/ipa/ipa_subdomains_ext_groups.c ++++ b/src/providers/ipa/ipa_subdomains_ext_groups.c +@@ -883,7 +883,7 @@ static void ipa_add_ad_memberships_get_next(struct tevent_req *req) + state->sdap_id_ctx->conn, + fq_name, + BE_FILTER_NAME, +- false, false); ++ false, false, false); + if (subreq == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "groups_get_send failed.\n"); + ret = ENOMEM; +diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h +index 6df7b3df44..7159d63564 100644 +--- a/src/providers/ldap/ldap_common.h ++++ b/src/providers/ldap/ldap_common.h +@@ -295,7 +295,8 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx, + const char *name, + int filter_type, + bool noexist_delete, +- bool no_members); ++ bool no_members, ++ bool set_non_posix); + int groups_get_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret); + + struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx, +@@ -306,7 +307,8 @@ struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx, + const char *filter_value, + int filter_type, + const char *extra_value, +- bool noexist_delete); ++ bool noexist_delete, ++ bool set_non_posix); + + int groups_by_user_recv(struct tevent_req *req, int *dp_error_out, int *sdap_ret); + +diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c +index fb81a17937..da54816bdf 100644 +--- a/src/providers/ldap/ldap_id.c ++++ b/src/providers/ldap/ldap_id.c +@@ -165,7 +165,8 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, + const char *filter_value, + int filter_type, + const char *extra_value, +- bool noexist_delete) ++ bool noexist_delete, ++ bool set_non_posix) + { + struct tevent_req *req; + struct users_get_state *state; +@@ -202,7 +203,7 @@ struct tevent_req *users_get_send(TALLOC_CTX *memctx, + state->filter_value = filter_value; + state->filter_type = filter_type; + +- if (state->domain->type == DOM_TYPE_APPLICATION) { ++ if (state->domain->type == DOM_TYPE_APPLICATION || set_non_posix) { + state->non_posix = true; + } + +@@ -582,7 +583,8 @@ static void users_get_done(struct tevent_req *subreq) + ret = sdap_fallback_local_user(state, state->shortname, uid, &usr_attrs); + if (ret == EOK) { + ret = sdap_save_user(state, state->ctx->opts, state->domain, +- usr_attrs[0], NULL, NULL, 0); ++ usr_attrs[0], NULL, NULL, 0, ++ state->non_posix); + } + } + } +@@ -665,7 +667,8 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx, + const char *filter_value, + int filter_type, + bool noexist_delete, +- bool no_members) ++ bool no_members, ++ bool set_non_posix) + { + struct tevent_req *req; + struct groups_get_state *state; +@@ -703,7 +706,7 @@ struct tevent_req *groups_get_send(TALLOC_CTX *memctx, + state->filter_value = filter_value; + state->filter_type = filter_type; + +- if (state->domain->type == DOM_TYPE_APPLICATION) { ++ if (state->domain->type == DOM_TYPE_APPLICATION || set_non_posix) { + state->non_posix = true; + } + +@@ -991,7 +994,8 @@ static void groups_get_done(struct tevent_req *subreq) + state->filter_value, + state->filter_type, + NULL, +- state->noexist_delete); ++ state->noexist_delete, ++ false); + if (subreq == NULL) { + tevent_req_error(req, ENOMEM); + return; +@@ -1159,7 +1163,8 @@ struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx, + const char *filter_value, + int filter_type, + const char *extra_value, +- bool noexist_delete) ++ bool noexist_delete, ++ bool set_non_posix) + { + struct tevent_req *req; + struct groups_by_user_state *state; +@@ -1188,7 +1193,7 @@ struct tevent_req *groups_by_user_send(TALLOC_CTX *memctx, + state->domain = sdom->dom; + state->sysdb = sdom->dom->sysdb; + +- if (state->domain->type == DOM_TYPE_APPLICATION) { ++ if (state->domain->type == DOM_TYPE_APPLICATION || set_non_posix) { + state->non_posix = true; + } + +@@ -1252,7 +1257,8 @@ static void groups_by_user_connect_done(struct tevent_req *subreq) + state->filter_value, + state->filter_type, + state->extra_value, +- state->attrs); ++ state->attrs, ++ state->non_posix); + if (!subreq) { + tevent_req_error(req, ENOMEM); + return; +@@ -1421,7 +1427,8 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx, + ar->filter_value, + ar->filter_type, + ar->extra_value, +- noexist_delete); ++ noexist_delete, ++ false); + break; + + case BE_REQ_GROUP: /* group */ +@@ -1429,7 +1436,7 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx, + sdom, conn, + ar->filter_value, + ar->filter_type, +- noexist_delete, false); ++ noexist_delete, false, false); + break; + + case BE_REQ_INITGROUPS: /* init groups for user */ +@@ -1446,7 +1453,7 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx, + ar->filter_value, + ar->filter_type, + ar->extra_value, +- noexist_delete); ++ noexist_delete, false); + break; + + case BE_REQ_SUBID_RANGES: +@@ -1545,7 +1552,8 @@ sdap_handle_acct_req_send(TALLOC_CTX *mem_ctx, + ar->filter_value, + ar->filter_type, + ar->extra_value, +- noexist_delete); ++ noexist_delete, ++ false); + break; + + default: /*fail*/ +@@ -1741,7 +1749,7 @@ static struct tevent_req *get_user_and_group_send(TALLOC_CTX *memctx, + subreq = groups_get_send(req, state->ev, state->id_ctx, + state->sdom, state->conn, + state->filter_val, state->filter_type, +- state->noexist_delete, false); ++ state->noexist_delete, false, false); + if (subreq == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "groups_get_send failed.\n"); + ret = ENOMEM; +@@ -1795,7 +1803,7 @@ static void get_user_and_group_groups_done(struct tevent_req *subreq) + subreq = users_get_send(req, state->ev, state->id_ctx, + state->sdom, user_conn, + state->filter_val, state->filter_type, NULL, +- state->noexist_delete); ++ state->noexist_delete, false); + if (subreq == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "users_get_send failed.\n"); + tevent_req_error(req, ENOMEM); +diff --git a/src/providers/ldap/sdap_async.h b/src/providers/ldap/sdap_async.h +index 02d84672e1..f9027a776d 100644 +--- a/src/providers/ldap/sdap_async.h ++++ b/src/providers/ldap/sdap_async.h +@@ -162,7 +162,8 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, + const char *name, + int filter_type, + const char *extra_value, +- const char **grp_attrs); ++ const char **grp_attrs, ++ bool set_non_posix); + int sdap_get_initgr_recv(struct tevent_req *req); + + struct tevent_req *sdap_exop_modify_passwd_send(TALLOC_CTX *memctx, +diff --git a/src/providers/ldap/sdap_async_initgroups.c b/src/providers/ldap/sdap_async_initgroups.c +index 4c8538e8a5..97be594a38 100644 +--- a/src/providers/ldap/sdap_async_initgroups.c ++++ b/src/providers/ldap/sdap_async_initgroups.c +@@ -2735,7 +2735,8 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, + const char *filter_value, + int filter_type, + const char *extra_value, +- const char **grp_attrs) ++ const char **grp_attrs, ++ bool set_non_posix) + { + struct tevent_req *req; + struct sdap_get_initgr_state *state; +@@ -2771,7 +2772,7 @@ struct tevent_req *sdap_get_initgr_send(TALLOC_CTX *memctx, + goto done; + } + +- if (state->dom->type == DOM_TYPE_APPLICATION) { ++ if (state->dom->type == DOM_TYPE_APPLICATION || set_non_posix) { + state->non_posix = true; + } + +@@ -3099,7 +3100,7 @@ static void sdap_get_initgr_user(struct tevent_req *subreq) + DEBUG(SSSDBG_TRACE_ALL, "Storing the user\n"); + + ret = sdap_save_user(state, state->opts, state->dom, state->orig_user, +- NULL, NULL, 0); ++ NULL, NULL, 0, state->non_posix); + if (ret) { + goto fail; + } +@@ -3435,7 +3436,7 @@ static void sdap_get_initgr_done(struct tevent_req *subreq) + subreq = groups_get_send(req, state->ev, state->id_ctx, + state->id_ctx->opts->sdom, state->conn, + gid, BE_FILTER_IDNUM, false, +- false); ++ false, false); + if (!subreq) { + ret = ENOMEM; + goto done; +diff --git a/src/providers/ldap/sdap_async_initgroups_ad.c b/src/providers/ldap/sdap_async_initgroups_ad.c +index bb18f35dc3..fb80c92429 100644 +--- a/src/providers/ldap/sdap_async_initgroups_ad.c ++++ b/src/providers/ldap/sdap_async_initgroups_ad.c +@@ -346,7 +346,7 @@ static errno_t sdap_ad_resolve_sids_step(struct tevent_req *req) + + subreq = groups_get_send(state, state->ev, state->id_ctx, sdap_domain, + state->conn, state->current_sid, +- BE_FILTER_SECID, false, true); ++ BE_FILTER_SECID, false, true, false); + if (subreq == NULL) { + return ENOMEM; + } +diff --git a/src/providers/ldap/sdap_async_users.c b/src/providers/ldap/sdap_async_users.c +index 9dcb59e233..728295d9df 100644 +--- a/src/providers/ldap/sdap_async_users.c ++++ b/src/providers/ldap/sdap_async_users.c +@@ -175,7 +175,8 @@ int sdap_save_user(TALLOC_CTX *memctx, + struct sysdb_attrs *attrs, + struct sysdb_attrs *mapped_attrs, + char **_usn_value, +- time_t now) ++ time_t now, ++ bool set_non_posix) + { + struct ldb_message_element *el; + int ret; +@@ -352,7 +353,7 @@ int sdap_save_user(TALLOC_CTX *memctx, + ret = sysdb_attrs_get_uint32_t(attrs, + opts->user_map[SDAP_AT_USER_UID].sys_name, + &uid); +- if (ret == ENOENT && dom->type == DOM_TYPE_APPLICATION) { ++ if (ret == ENOENT && (dom->type == DOM_TYPE_APPLICATION || set_non_posix)) { + DEBUG(SSSDBG_TRACE_INTERNAL, + "Marking object as non-POSIX and setting ID=0!\n"); + ret = sdap_set_non_posix_flag(user_attrs, +@@ -450,7 +451,7 @@ int sdap_save_user(TALLOC_CTX *memctx, + ret = sysdb_attrs_get_uint32_t(attrs, + opts->user_map[SDAP_AT_USER_GID].sys_name, + &gid); +- if (ret == ENOENT && dom->type == DOM_TYPE_APPLICATION) { ++ if (ret == ENOENT && (dom->type == DOM_TYPE_APPLICATION || set_non_posix)) { + DEBUG(SSSDBG_TRACE_INTERNAL, + "Marking object as non-POSIX and setting ID=0!\n"); + ret = sdap_set_non_posix_flag(attrs, +@@ -696,7 +697,7 @@ int sdap_save_users(TALLOC_CTX *memctx, + usn_value = NULL; + + ret = sdap_save_user(tmpctx, opts, dom, users[i], mapped_attrs, +- &usn_value, now); ++ &usn_value, now, false); + + /* Do not fail completely on errors. + * Just report the failure to save and go on */ +diff --git a/src/providers/ldap/sdap_users.h b/src/providers/ldap/sdap_users.h +index a6d088a6d7..74284cd0ac 100644 +--- a/src/providers/ldap/sdap_users.h ++++ b/src/providers/ldap/sdap_users.h +@@ -36,6 +36,7 @@ int sdap_save_user(TALLOC_CTX *memctx, + struct sysdb_attrs *attrs, + struct sysdb_attrs *mapped_attrs, + char **_usn_value, +- time_t now); ++ time_t now, ++ bool set_non_posix); + + #endif /* _SDAP_USERS_H_ */ diff --git a/SOURCES/0016-ipa-Add-BUILD_PASSKEY-conditional-for-passkey-codepath.patch b/SOURCES/0016-ipa-Add-BUILD_PASSKEY-conditional-for-passkey-codepath.patch new file mode 100644 index 0000000..fe87291 --- /dev/null +++ b/SOURCES/0016-ipa-Add-BUILD_PASSKEY-conditional-for-passkey-codepath.patch @@ -0,0 +1,57 @@ +From 7cf9a1ff0e876ea0970a3f0b3c389b87be834b4f Mon Sep 17 00:00:00 2001 +From: Justin Stephenson +Date: Tue, 15 Aug 2023 13:33:03 -0400 +Subject: [PATCH] ipa: Add `BUILD_PASSKEY` conditional for passkey codepath + +Reviewed-by: Alexey Tikhonov +Reviewed-by: Iker Pedrosa +--- + Makefile.am | 2 ++ + src/providers/ipa/ipa_subdomains.c | 4 ++++ + 2 files changed, 6 insertions(+) + +diff --git a/Makefile.am b/Makefile.am +index 273ac1c523..c68461675f 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -4581,8 +4581,10 @@ if BUILD_SSH + libsss_ipa_la_SOURCES += src/providers/ipa/ipa_hostid.c + endif + ++if BUILD_PASSKEY + libsss_ipa_la_SOURCES += \ + src/providers/ipa/ipa_subdomains_passkey.c ++endif # BUILD_PASSKEY + + libsss_ad_la_SOURCES = \ + src/providers/ad/ad_opts.c \ +diff --git a/src/providers/ipa/ipa_subdomains.c b/src/providers/ipa/ipa_subdomains.c +index 34cedc0362..e19343a77d 100644 +--- a/src/providers/ipa/ipa_subdomains.c ++++ b/src/providers/ipa/ipa_subdomains.c +@@ -30,7 +30,9 @@ + #include "providers/ipa/ipa_id.h" + #include "providers/ipa/ipa_opts.h" + #include "providers/ipa/ipa_config.h" ++#ifdef BUILD_PASSKEY + #include "providers/ipa/ipa_subdomains_passkey.h" ++#endif /* BUILD_PASSKEY */ + + #include + +@@ -2762,6 +2764,7 @@ static void ipa_subdomains_refresh_certmap_done(struct tevent_req *subreq) + /* Not good, but let's try to continue with other server side options */ + } + ++#ifdef BUILD_PASSKEY + subreq = ipa_subdomains_passkey_send(state, state->ev, state->sd_ctx, + sdap_id_op_handle(state->sdap_op)); + if (subreq == NULL) { +@@ -2792,6 +2795,7 @@ static void ipa_subdomains_refresh_passkey_done(struct tevent_req *subreq) + DEBUG(SSSDBG_IMPORTANT_INFO, "Passkey feature is not configured " + "on IPA server"); + } ++#endif /* BUILD_PASSKEY */ + + subreq = ipa_subdomains_master_send(state, state->ev, state->sd_ctx, + sdap_id_op_handle(state->sdap_op)); diff --git a/SOURCES/0017-pam-Conditionalize-passkey-code.patch b/SOURCES/0017-pam-Conditionalize-passkey-code.patch new file mode 100644 index 0000000..8e39651 --- /dev/null +++ b/SOURCES/0017-pam-Conditionalize-passkey-code.patch @@ -0,0 +1,885 @@ +From eadee9a2a8f0dfe4f22c460537d6c87c493fa622 Mon Sep 17 00:00:00 2001 +From: Justin Stephenson +Date: Mon, 14 Aug 2023 14:42:51 -0400 +Subject: [PATCH] pam: Conditionalize passkey code + +Reviewed-by: Alexey Tikhonov +Reviewed-by: Iker Pedrosa +--- + Makefile.am | 4 +- + src/responder/pam/pamsrv_cmd.c | 364 +---------------------------- + src/responder/pam/pamsrv_passkey.c | 351 ++++++++++++++++++++++++++++ + src/responder/pam/pamsrv_passkey.h | 8 + + 4 files changed, 372 insertions(+), 355 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index 066f5d94ee..273ac1c523 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -1564,8 +1564,10 @@ sssd_pam_SOURCES = \ + src/responder/pam/pam_prompting_config.c \ + src/sss_client/pam_sss_prompt_config.c \ + src/responder/pam/pam_helpers.c \ +- src/responder/pam/pamsrv_passkey.c \ + $(SSSD_RESPONDER_OBJ) ++if BUILD_PASSKEY ++ sssd_pam_SOURCES += src/responder/pam/pamsrv_passkey.c ++endif + sssd_pam_CFLAGS = \ + $(AM_CFLAGS) \ + $(GSSAPI_KRB5_CFLAGS) \ +diff --git a/src/responder/pam/pamsrv_cmd.c b/src/responder/pam/pamsrv_cmd.c +index 94cbf13e8d..eed283f4e9 100644 +--- a/src/responder/pam/pamsrv_cmd.c ++++ b/src/responder/pam/pamsrv_cmd.c +@@ -53,12 +53,6 @@ struct pam_initgroup_enum_str { + const char *option; + }; + +-struct pam_passkey_table_data { +- hash_table_t *table; +- char *key; +- struct pk_child_user_data *data; +-}; +- + struct pam_initgroup_enum_str pam_initgroup_enum_str[] = { + { PAM_INITGR_NEVER, "never" }, + { PAM_INITGR_NO_SESSION, "no_session" }, +@@ -108,10 +102,6 @@ static errno_t check_cert(TALLOC_CTX *mctx, + struct pam_auth_req *preq, + struct pam_data *pd); + +-errno_t passkey_kerberos(struct pam_ctx *pctx, +- struct pam_data *pd, +- struct pam_auth_req *preq); +- + int pam_check_user_done(struct pam_auth_req *preq, int ret); + + static errno_t pack_user_info_msg(TALLOC_CTX *mem_ctx, +@@ -1173,229 +1163,6 @@ static int pam_reply_sr_export_shell(struct pam_auth_req *preq, + return ret; + } + +-errno_t decode_pam_passkey_msg(TALLOC_CTX *mem_ctx, +- uint8_t *buf, +- size_t len, +- struct pk_child_user_data **_data) +-{ +- +- size_t p = 0; +- size_t pctr = 0; +- errno_t ret; +- size_t offset; +- struct pk_child_user_data *data = NULL; +- TALLOC_CTX *tmp_ctx; +- +- tmp_ctx = talloc_new(NULL); +- if (tmp_ctx == NULL) { +- return ENOMEM; +- } +- +- data = talloc_zero(tmp_ctx, struct pk_child_user_data); +- if (data == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, "Failed to talloc passkey data.\n"); +- ret = ENOMEM; +- goto done; +- } +- +- data->user_verification = talloc_strdup(data, (char *) &buf[p]); +- if (data->user_verification == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, "Failed to strdup passkey prompt.\n"); +- ret = ENOMEM; +- goto done; +- } +- +- offset = strlen(data->user_verification) + 1; +- if (offset >= len) { +- DEBUG(SSSDBG_OP_FAILURE, "passkey prompt offset failure.\n"); +- ret = EIO; +- goto done; +- } +- +- data->crypto_challenge = talloc_strdup(data, (char *) &buf[p + offset]); +- if (data->crypto_challenge == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, "Failed to strdup passkey challenge.\n"); +- ret = ENOMEM; +- goto done; +- } +- +- offset += strlen(data->crypto_challenge) + 1; +- if (offset >= len) { +- DEBUG(SSSDBG_OP_FAILURE, "passkey challenge offset failure.\n"); +- ret = EIO; +- goto done; +- } +- +- +- data->domain = talloc_strdup(data, (char *) &buf[p] + offset); +- if (data->domain == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, "Failed to strdup passkey domain.\n"); +- ret = ENOMEM; +- goto done; +- } +- +- offset += strlen(data->domain) + 1; +- if (offset >= len) { +- DEBUG(SSSDBG_OP_FAILURE, "passkey domain offset failure.\n"); +- ret = EIO; +- goto done; +- } +- +- SAFEALIGN_COPY_UINT32(&data->num_credentials, &buf[p + offset], &pctr); +- size_t list_sz = (size_t) data->num_credentials; +- +- offset += sizeof(uint32_t); +- +- data->key_handles = talloc_zero_array(data, const char *, list_sz); +- +- for (int i = 0; i < list_sz; i++) { +- data->key_handles[i] = talloc_strdup(data->key_handles, (char *) &buf[p + offset]); +- if (data->key_handles[i] == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, "Failed to strdup passkey list.\n"); +- ret = ENOMEM; +- goto done; +- } +- +- offset += strlen(data->key_handles[i]) + 1; +- } +- +- *_data = talloc_steal(mem_ctx, data); +- +- ret = EOK; +-done: +- talloc_free(tmp_ctx); +- return ret; +-} +- +- +-errno_t save_passkey_data(TALLOC_CTX *mem_ctx, +- struct pam_ctx *pctx, +- struct pk_child_user_data *data, +- struct pam_auth_req *preq) +-{ +- char *pk_key; +- errno_t ret; +- TALLOC_CTX *tmp_ctx; +- +- tmp_ctx = talloc_new(NULL); +- if (tmp_ctx == NULL) { +- return ENOMEM; +- } +- +- /* Passkey data (pk_table_data) is stolen onto client ctx, it will +- * be freed when the client closes, and the sss_ptr_hash interface +- * takes care of automatically removing it from the hash table then */ +- pctx->pk_table_data = talloc_zero(tmp_ctx, struct pam_passkey_table_data); +- if (pctx->pk_table_data == NULL) { +- return ENOMEM; +- } +- +- if (pctx->pk_table_data->table == NULL) { +- pctx->pk_table_data->table = sss_ptr_hash_create(pctx->pk_table_data, +- NULL, NULL); +- if (pctx->pk_table_data->table == NULL) { +- ret = ENOMEM; +- goto done; +- } +- } +- +- pk_key = talloc_asprintf(tmp_ctx, "%s", data->crypto_challenge); +- if (pk_key == NULL) { +- ret = ENOMEM; +- goto done; +- } +- +- pctx->pk_table_data->key = talloc_strdup(pctx->pk_table_data, pk_key); +- if (pctx->pk_table_data->key == NULL) { +- ret = ENOMEM; +- goto done; +- } +- +- ret = sss_ptr_hash_add(pctx->pk_table_data->table, pk_key, data, +- struct pk_child_user_data); +- if (ret == EEXIST) { +- DEBUG(SSSDBG_TRACE_FUNC, "pk_table key [%s] already exists\n", +- pk_key); +- goto done; +- } else if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, "Unable to add pk data to hash table " +- "[%d]: %s\n", ret, sss_strerror(ret)); +- goto done; +- } +- +- talloc_steal(mem_ctx, pctx->pk_table_data); +- pctx->pk_table_data->data = talloc_steal(mem_ctx, data); +- +- ret = EOK; +- +-done: +- talloc_free(tmp_ctx); +- +- return ret; +-} +- +-errno_t pam_eval_passkey_response(struct pam_ctx *pctx, +- struct pam_data *pd, +- struct pam_auth_req *preq, +- bool *_pk_preauth_done) +-{ +- struct response_data *pk_resp; +- struct pk_child_user_data *pk_data; +- errno_t ret; +- TALLOC_CTX *tmp_ctx; +- +- tmp_ctx = talloc_new(NULL); +- if (tmp_ctx == NULL) { +- return ENOMEM; +- } +- +- pk_resp = pd->resp_list; +- +- while (pk_resp != NULL) { +- switch (pk_resp->type) { +- case SSS_PAM_PASSKEY_KRB_INFO: +- if (!pctx->passkey_auth) { +- /* Passkey auth is disabled. To avoid passkey prompts appearing, +- * don't send SSS_PAM_PASSKEY_KRB_INFO to the client and +- * add a dummy response to fallback to normal auth */ +- pk_resp->do_not_send_to_client = true; +- ret = pam_add_response(pd, SSS_OTP, 0, NULL); +- if (ret != EOK) { +- DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n"); +- goto done; +- } +- break; +- } +- ret = decode_pam_passkey_msg(tmp_ctx, pk_resp->data, pk_resp->len, &pk_data); +- if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, "Failed to decode passkey msg\n"); +- ret = EIO; +- goto done; +- } +- +- ret = save_passkey_data(preq->cctx, pctx, pk_data, preq); +- if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, "Failed to save passkey msg\n"); +- ret = EIO; +- goto done; +- } +- break; +- /* Passkey non-kerberos preauth has already run */ +- case SSS_PAM_PASSKEY_INFO: +- *_pk_preauth_done = true; +- default: +- break; +- } +- pk_resp = pk_resp->next; +- } +- +- ret = EOK; +-done: +- talloc_free(tmp_ctx); +- +- return ret; +-} +- + void pam_reply(struct pam_auth_req *preq) + { + struct cli_ctx *cctx; +@@ -1692,6 +1459,7 @@ void pam_reply(struct pam_auth_req *preq) + "using defaults.\n"); + } + ++#ifdef BUILD_PASSKEY + ret = pam_eval_passkey_response(pctx, pd, preq, &pk_preauth_done); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "Failed to eval passkey response\n"); +@@ -1706,6 +1474,7 @@ void pam_reply(struct pam_auth_req *preq) + pam_check_user_done(preq, ret); + return; + } ++#endif /* BUILD_PASSKEY */ + } + + /* +@@ -2163,6 +1932,7 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd) + * It is checked in pam_reply() to avoid an endless loop */ + preq->passkey_data_exists = true; + ++#ifdef BUILD_PASSKEY + if ((pd->cmd == SSS_PAM_AUTHENTICATE)) { + if (may_do_passkey_auth(pctx, pd)) { + if (sss_authtok_get_type(pd->authtok) == SSS_AUTHTOK_TYPE_PASSKEY_KRB) { +@@ -2175,6 +1945,7 @@ static int pam_forwarder(struct cli_ctx *cctx, int pam_cmd) + } + } + } ++#endif /* BUILD_PASSKEY */ + + ret = pam_check_user_search(preq); + +@@ -2573,6 +2344,7 @@ static void pam_forwarder_cb(struct tevent_req *req) + goto done; + } + ++#ifdef BUILD_PASSKEY + /* This is set to false inside passkey_local() if no passkey data is found. + * It is checked in pam_reply() to avoid an endless loop */ + preq->passkey_data_exists = true; +@@ -2589,6 +2361,7 @@ static void pam_forwarder_cb(struct tevent_req *req) + } + } + } ++#endif /* BUILD_PASSKEY */ + + ret = pam_check_user_search(preq); + +@@ -2910,127 +2683,6 @@ static bool pam_can_user_cache_auth(struct sss_domain_info *domain, + return result; + } + +-void passkey_kerberos_cb(struct tevent_req *req) +-{ +- struct pam_auth_req *preq = tevent_req_callback_data(req, +- struct pam_auth_req); +- errno_t ret = EOK; +- int child_status; +- +- ret = pam_passkey_auth_recv(req, &child_status); +- talloc_free(req); +- if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, "PAM passkey auth failed [%d]: %s\n", +- ret, sss_strerror(ret)); +- goto done; +- } +- +- DEBUG(SSSDBG_TRACE_FUNC, "passkey child finished with status [%d]\n", child_status); +- +- pam_check_user_search(preq); +- +-done: +- pam_check_user_done(preq, ret); +-} +- +-errno_t passkey_kerberos(struct pam_ctx *pctx, +- struct pam_data *pd, +- struct pam_auth_req *preq) +-{ +- errno_t ret; +- const char *prompt; +- const char *key; +- const char *pin; +- size_t pin_len; +- struct pk_child_user_data *data; +- struct tevent_req *req; +- int timeout; +- char *verify_opts; +- bool debug_libfido2; +- enum passkey_user_verification verification; +- +- ret = sss_authtok_get_passkey(preq, preq->pd->authtok, +- &prompt, &key, &pin, &pin_len); +- if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, +- "Failure to get passkey authtok\n"); +- return EIO; +- } +- +- if (prompt == NULL || key == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, +- "Passkey prompt and key are missing or invalid.\n"); +- return EIO; +- } +- +- data = sss_ptr_hash_lookup(pctx->pk_table_data->table, key, +- struct pk_child_user_data); +- if (data == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, +- "Failed to lookup passkey authtok\n"); +- return EIO; +- } +- +- ret = confdb_get_int(pctx->rctx->cdb, CONFDB_PAM_CONF_ENTRY, +- CONFDB_PAM_PASSKEY_CHILD_TIMEOUT, PASSKEY_CHILD_TIMEOUT_DEFAULT, +- &timeout); +- if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, +- "Failed to read passkey_child_timeout from confdb: [%d]: %s\n", +- ret, sss_strerror(ret)); +- goto done; +- } +- +- ret = confdb_get_string(pctx->rctx->cdb, preq, CONFDB_MONITOR_CONF_ENTRY, +- CONFDB_MONITOR_PASSKEY_VERIFICATION, NULL, +- &verify_opts); +- if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, +- "Failed to read '"CONFDB_MONITOR_PASSKEY_VERIFICATION"' from confdb: [%d]: %s\n", +- ret, sss_strerror(ret)); +- goto done; +- } +- +- /* Always use verification sent from passkey krb5 plugin */ +- ret = read_passkey_conf_verification(preq, verify_opts, NULL); +- if (ret != EOK) { +- DEBUG(SSSDBG_MINOR_FAILURE, "Unable to parse passkey verificaton options.\n"); +- } +- +- if (strcasecmp(data->user_verification, "false") == 0) { +- verification = PAM_PASSKEY_VERIFICATION_OFF; +- } else { +- verification = PAM_PASSKEY_VERIFICATION_ON; +- } +- +- ret = confdb_get_bool(pctx->rctx->cdb, CONFDB_PAM_CONF_ENTRY, +- CONFDB_PAM_PASSKEY_DEBUG_LIBFIDO2, false, +- &debug_libfido2); +- if (ret != EOK) { +- DEBUG(SSSDBG_OP_FAILURE, +- "Failed to read '"CONFDB_PAM_PASSKEY_DEBUG_LIBFIDO2"' from confdb: [%d]: %s\n", +- ret, sss_strerror(ret)); +- goto done; +- } +- +- req = pam_passkey_auth_send(preq->cctx, preq->cctx->ev, timeout, debug_libfido2, +- verification, pd, data, true); +- if (req == NULL) { +- DEBUG(SSSDBG_OP_FAILURE, "passkey auth send failed [%d]: [%s]\n", +- ret, sss_strerror(ret)); +- goto done; +- } +- +- tevent_req_set_callback(req, passkey_kerberos_cb, preq); +- +- ret = EAGAIN; +- +-done: +- +- return ret; +- +-} +- + static void pam_dom_forwarder(struct pam_auth_req *preq) + { + TALLOC_CTX *tmp_ctx = NULL; +@@ -3086,7 +2738,11 @@ static void pam_dom_forwarder(struct pam_auth_req *preq) + } + + /* Skip online auth when local auth policy = only */ ++#ifdef BUILD_PASSKEY + if (may_do_cert_auth(pctx, preq->pd) || may_do_passkey_auth(pctx, preq->pd)) { ++#else ++ if (may_do_cert_auth(pctx, preq->pd)) { ++#endif /* BUILD_PASSKEY */ + if (preq->domain->name != NULL) { + ret = pam_eval_local_auth_policy(preq->cctx, pctx, preq->pd, preq, + &sc_auth, +diff --git a/src/responder/pam/pamsrv_passkey.c b/src/responder/pam/pamsrv_passkey.c +index eb62db03d7..57cba845ae 100644 +--- a/src/responder/pam/pamsrv_passkey.c ++++ b/src/responder/pam/pamsrv_passkey.c +@@ -32,6 +32,12 @@ struct pam_passkey_verification_enum_str { + const char *option; + }; + ++struct pam_passkey_table_data { ++ hash_table_t *table; ++ char *key; ++ struct pk_child_user_data *data; ++}; ++ + struct pam_passkey_verification_enum_str pam_passkey_verification_enum_str[] = { + { PAM_PASSKEY_VERIFICATION_ON, "on" }, + { PAM_PASSKEY_VERIFICATION_OFF, "off" }, +@@ -85,6 +91,128 @@ struct passkey_get_mapping_state { + struct cache_req_result *result; + }; + ++void passkey_kerberos_cb(struct tevent_req *req) ++{ ++ struct pam_auth_req *preq = tevent_req_callback_data(req, ++ struct pam_auth_req); ++ errno_t ret = EOK; ++ int child_status; ++ ++ ret = pam_passkey_auth_recv(req, &child_status); ++ talloc_free(req); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, "PAM passkey auth failed [%d]: %s\n", ++ ret, sss_strerror(ret)); ++ goto done; ++ } ++ ++ DEBUG(SSSDBG_TRACE_FUNC, "passkey child finished with status [%d]\n", child_status); ++ ++ pam_check_user_search(preq); ++ ++done: ++ pam_check_user_done(preq, ret); ++} ++ ++errno_t passkey_kerberos(struct pam_ctx *pctx, ++ struct pam_data *pd, ++ struct pam_auth_req *preq) ++{ ++ errno_t ret; ++ const char *prompt; ++ const char *key; ++ const char *pin; ++ size_t pin_len; ++ struct pk_child_user_data *data; ++ struct tevent_req *req; ++ int timeout; ++ char *verify_opts; ++ bool debug_libfido2; ++ enum passkey_user_verification verification; ++ ++ ret = sss_authtok_get_passkey(preq, preq->pd->authtok, ++ &prompt, &key, &pin, &pin_len); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "Failure to get passkey authtok\n"); ++ return EIO; ++ } ++ ++ if (prompt == NULL || key == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "Passkey prompt and key are missing or invalid.\n"); ++ return EIO; ++ } ++ ++ data = sss_ptr_hash_lookup(pctx->pk_table_data->table, key, ++ struct pk_child_user_data); ++ if (data == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "Failed to lookup passkey authtok\n"); ++ return EIO; ++ } ++ ++ ret = confdb_get_int(pctx->rctx->cdb, CONFDB_PAM_CONF_ENTRY, ++ CONFDB_PAM_PASSKEY_CHILD_TIMEOUT, PASSKEY_CHILD_TIMEOUT_DEFAULT, ++ &timeout); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "Failed to read passkey_child_timeout from confdb: [%d]: %s\n", ++ ret, sss_strerror(ret)); ++ goto done; ++ } ++ ++ ret = confdb_get_string(pctx->rctx->cdb, preq, CONFDB_MONITOR_CONF_ENTRY, ++ CONFDB_MONITOR_PASSKEY_VERIFICATION, NULL, ++ &verify_opts); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "Failed to read '"CONFDB_MONITOR_PASSKEY_VERIFICATION"' from confdb: [%d]: %s\n", ++ ret, sss_strerror(ret)); ++ goto done; ++ } ++ ++ /* Always use verification sent from passkey krb5 plugin */ ++ ret = read_passkey_conf_verification(preq, verify_opts, NULL); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_MINOR_FAILURE, "Unable to parse passkey verificaton options.\n"); ++ } ++ ++ if (strcasecmp(data->user_verification, "false") == 0) { ++ verification = PAM_PASSKEY_VERIFICATION_OFF; ++ } else { ++ verification = PAM_PASSKEY_VERIFICATION_ON; ++ } ++ ++ ret = confdb_get_bool(pctx->rctx->cdb, CONFDB_PAM_CONF_ENTRY, ++ CONFDB_PAM_PASSKEY_DEBUG_LIBFIDO2, false, ++ &debug_libfido2); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, ++ "Failed to read '"CONFDB_PAM_PASSKEY_DEBUG_LIBFIDO2"' from confdb: [%d]: %s\n", ++ ret, sss_strerror(ret)); ++ goto done; ++ } ++ ++ req = pam_passkey_auth_send(preq->cctx, preq->cctx->ev, timeout, debug_libfido2, ++ verification, pd, data, true); ++ if (req == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "passkey auth send failed [%d]: [%s]\n", ++ ret, sss_strerror(ret)); ++ goto done; ++ } ++ ++ tevent_req_set_callback(req, passkey_kerberos_cb, preq); ++ ++ ret = EAGAIN; ++ ++done: ++ ++ return ret; ++ ++} ++ ++ + errno_t passkey_local(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct pam_ctx *pam_ctx, +@@ -996,6 +1124,229 @@ errno_t pam_passkey_auth_recv(struct tevent_req *req, + return EOK; + } + ++errno_t decode_pam_passkey_msg(TALLOC_CTX *mem_ctx, ++ uint8_t *buf, ++ size_t len, ++ struct pk_child_user_data **_data) ++{ ++ ++ size_t p = 0; ++ size_t pctr = 0; ++ errno_t ret; ++ size_t offset; ++ struct pk_child_user_data *data = NULL; ++ TALLOC_CTX *tmp_ctx; ++ ++ tmp_ctx = talloc_new(NULL); ++ if (tmp_ctx == NULL) { ++ return ENOMEM; ++ } ++ ++ data = talloc_zero(tmp_ctx, struct pk_child_user_data); ++ if (data == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "Failed to talloc passkey data.\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ data->user_verification = talloc_strdup(data, (char *) &buf[p]); ++ if (data->user_verification == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "Failed to strdup passkey prompt.\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ offset = strlen(data->user_verification) + 1; ++ if (offset >= len) { ++ DEBUG(SSSDBG_OP_FAILURE, "passkey prompt offset failure.\n"); ++ ret = EIO; ++ goto done; ++ } ++ ++ data->crypto_challenge = talloc_strdup(data, (char *) &buf[p + offset]); ++ if (data->crypto_challenge == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "Failed to strdup passkey challenge.\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ offset += strlen(data->crypto_challenge) + 1; ++ if (offset >= len) { ++ DEBUG(SSSDBG_OP_FAILURE, "passkey challenge offset failure.\n"); ++ ret = EIO; ++ goto done; ++ } ++ ++ ++ data->domain = talloc_strdup(data, (char *) &buf[p] + offset); ++ if (data->domain == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "Failed to strdup passkey domain.\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ offset += strlen(data->domain) + 1; ++ if (offset >= len) { ++ DEBUG(SSSDBG_OP_FAILURE, "passkey domain offset failure.\n"); ++ ret = EIO; ++ goto done; ++ } ++ ++ SAFEALIGN_COPY_UINT32(&data->num_credentials, &buf[p + offset], &pctr); ++ size_t list_sz = (size_t) data->num_credentials; ++ ++ offset += sizeof(uint32_t); ++ ++ data->key_handles = talloc_zero_array(data, const char *, list_sz); ++ ++ for (int i = 0; i < list_sz; i++) { ++ data->key_handles[i] = talloc_strdup(data->key_handles, (char *) &buf[p + offset]); ++ if (data->key_handles[i] == NULL) { ++ DEBUG(SSSDBG_OP_FAILURE, "Failed to strdup passkey list.\n"); ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ offset += strlen(data->key_handles[i]) + 1; ++ } ++ ++ *_data = talloc_steal(mem_ctx, data); ++ ++ ret = EOK; ++done: ++ talloc_free(tmp_ctx); ++ return ret; ++} ++ ++errno_t save_passkey_data(TALLOC_CTX *mem_ctx, ++ struct pam_ctx *pctx, ++ struct pk_child_user_data *data, ++ struct pam_auth_req *preq) ++{ ++ char *pk_key; ++ errno_t ret; ++ TALLOC_CTX *tmp_ctx; ++ ++ tmp_ctx = talloc_new(NULL); ++ if (tmp_ctx == NULL) { ++ return ENOMEM; ++ } ++ ++ /* Passkey data (pk_table_data) is stolen onto client ctx, it will ++ * be freed when the client closes, and the sss_ptr_hash interface ++ * takes care of automatically removing it from the hash table then */ ++ pctx->pk_table_data = talloc_zero(tmp_ctx, struct pam_passkey_table_data); ++ if (pctx->pk_table_data == NULL) { ++ return ENOMEM; ++ } ++ ++ if (pctx->pk_table_data->table == NULL) { ++ pctx->pk_table_data->table = sss_ptr_hash_create(pctx->pk_table_data, ++ NULL, NULL); ++ if (pctx->pk_table_data->table == NULL) { ++ ret = ENOMEM; ++ goto done; ++ } ++ } ++ ++ pk_key = talloc_asprintf(tmp_ctx, "%s", data->crypto_challenge); ++ if (pk_key == NULL) { ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ pctx->pk_table_data->key = talloc_strdup(pctx->pk_table_data, pk_key); ++ if (pctx->pk_table_data->key == NULL) { ++ ret = ENOMEM; ++ goto done; ++ } ++ ++ ret = sss_ptr_hash_add(pctx->pk_table_data->table, pk_key, data, ++ struct pk_child_user_data); ++ if (ret == EEXIST) { ++ DEBUG(SSSDBG_TRACE_FUNC, "pk_table key [%s] already exists\n", ++ pk_key); ++ goto done; ++ } else if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, "Unable to add pk data to hash table " ++ "[%d]: %s\n", ret, sss_strerror(ret)); ++ goto done; ++ } ++ ++ talloc_steal(mem_ctx, pctx->pk_table_data); ++ pctx->pk_table_data->data = talloc_steal(mem_ctx, data); ++ ++ ret = EOK; ++ ++done: ++ talloc_free(tmp_ctx); ++ ++ return ret; ++} ++ ++errno_t pam_eval_passkey_response(struct pam_ctx *pctx, ++ struct pam_data *pd, ++ struct pam_auth_req *preq, ++ bool *_pk_preauth_done) ++{ ++ struct response_data *pk_resp; ++ struct pk_child_user_data *pk_data; ++ errno_t ret; ++ TALLOC_CTX *tmp_ctx; ++ ++ tmp_ctx = talloc_new(NULL); ++ if (tmp_ctx == NULL) { ++ return ENOMEM; ++ } ++ ++ pk_resp = pd->resp_list; ++ ++ while (pk_resp != NULL) { ++ switch (pk_resp->type) { ++ case SSS_PAM_PASSKEY_KRB_INFO: ++ if (!pctx->passkey_auth) { ++ /* Passkey auth is disabled. To avoid passkey prompts appearing, ++ * don't send SSS_PAM_PASSKEY_KRB_INFO to the client and ++ * add a dummy response to fallback to normal auth */ ++ pk_resp->do_not_send_to_client = true; ++ ret = pam_add_response(pd, SSS_OTP, 0, NULL); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_CRIT_FAILURE, "pam_add_response failed.\n"); ++ goto done; ++ } ++ break; ++ } ++ ret = decode_pam_passkey_msg(tmp_ctx, pk_resp->data, pk_resp->len, &pk_data); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, "Failed to decode passkey msg\n"); ++ ret = EIO; ++ goto done; ++ } ++ ++ ret = save_passkey_data(preq->cctx, pctx, pk_data, preq); ++ if (ret != EOK) { ++ DEBUG(SSSDBG_OP_FAILURE, "Failed to save passkey msg\n"); ++ ret = EIO; ++ goto done; ++ } ++ break; ++ /* Passkey non-kerberos preauth has already run */ ++ case SSS_PAM_PASSKEY_INFO: ++ *_pk_preauth_done = true; ++ default: ++ break; ++ } ++ pk_resp = pk_resp->next; ++ } ++ ++ ret = EOK; ++done: ++ talloc_free(tmp_ctx); ++ ++ return ret; ++} ++ ++ + static void + pam_passkey_auth_done(int child_status, + struct tevent_signal *sige, +diff --git a/src/responder/pam/pamsrv_passkey.h b/src/responder/pam/pamsrv_passkey.h +index 6b0d62071f..7c5a532e91 100644 +--- a/src/responder/pam/pamsrv_passkey.h ++++ b/src/responder/pam/pamsrv_passkey.h +@@ -23,6 +23,7 @@ + + #include + #include "util/util.h" ++#include "util/sss_ptr_hash.h" + #include "responder/common/responder.h" + #include "responder/common/cache_req/cache_req.h" + #include "responder/pam/pamsrv.h" +@@ -40,6 +41,9 @@ errno_t passkey_local(TALLOC_CTX *mem_ctx, + struct pam_ctx *pam_ctx, + struct pam_auth_req *preq, + struct pam_data *pd); ++errno_t passkey_kerberos(struct pam_ctx *pctx, ++ struct pam_data *pd, ++ struct pam_auth_req *preq); + + struct pk_child_user_data { + /* Both Kerberos and non-kerberos */ +@@ -69,6 +73,10 @@ struct tevent_req *pam_passkey_auth_send(TALLOC_CTX *mem_ctx, + bool kerberos_pa); + errno_t pam_passkey_auth_recv(struct tevent_req *req, + int *child_status); ++errno_t pam_eval_passkey_response(struct pam_ctx *pctx, ++ struct pam_data *pd, ++ struct pam_auth_req *preq, ++ bool *_pk_preauth_done); + bool may_do_passkey_auth(struct pam_ctx *pctx, + struct pam_data *pd); + diff --git a/SOURCES/0018-Makefile-Respect-BUILD_PASSKEY-conditional.patch b/SOURCES/0018-Makefile-Respect-BUILD_PASSKEY-conditional.patch new file mode 100644 index 0000000..2afde84 --- /dev/null +++ b/SOURCES/0018-Makefile-Respect-BUILD_PASSKEY-conditional.patch @@ -0,0 +1,87 @@ +From a20dadc7ec9b21687356d1b0b0218db89f438c67 Mon Sep 17 00:00:00 2001 +From: Justin Stephenson +Date: Tue, 15 Aug 2023 16:27:39 -0400 +Subject: [PATCH] Makefile: Respect `BUILD_PASSKEY` conditional + +Reviewed-by: Alexey Tikhonov +Reviewed-by: Iker Pedrosa +--- + Makefile.am | 11 ++++++++--- + src/providers/krb5/krb5_child.c | 5 +++++ + 2 files changed, 13 insertions(+), 3 deletions(-) + +diff --git a/Makefile.am b/Makefile.am +index a3952ce78d..066f5d94ee 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -1319,7 +1319,9 @@ endif + if BUILD_SYSTEMTAP + libsss_util_la_LIBADD += stap_generated_probes.lo + endif ++if BUILD_PASSKEY + libsss_util_la_SOURCES += src/db/sysdb_passkey_user_verification.c ++endif # BUILD_PASSKEY + libsss_util_la_LDFLAGS = -avoid-version + + pkglib_LTLIBRARIES += libsss_semanage.la +@@ -2621,7 +2623,6 @@ pam_srv_tests_SOURCES = \ + src/responder/pam/pamsrv_cmd.c \ + src/responder/pam/pamsrv_p11.c \ + src/responder/pam/pamsrv_gssapi.c \ +- src/responder/pam/pamsrv_passkey.c \ + src/responder/pam/pam_helpers.c \ + src/responder/pam/pamsrv_dp.c \ + src/responder/pam/pam_prompting_config.c \ +@@ -2655,6 +2656,9 @@ pam_srv_tests_LDADD = \ + libsss_iface.la \ + libsss_sbus.la \ + $(NULL) ++if BUILD_PASSKEY ++ pam_srv_tests_SOURCES += src/responder/pam/pamsrv_passkey.c ++endif # BUILD_PASSKEY + + EXTRA_ssh_srv_tests_DEPENDENCIES = \ + $(ldblib_LTLIBRARIES) \ +@@ -4578,7 +4582,6 @@ endif + libsss_ipa_la_SOURCES += \ + src/providers/ipa/ipa_subdomains_passkey.c + +- + libsss_ad_la_SOURCES = \ + src/providers/ad/ad_opts.c \ + src/providers/ad/ad_common.c \ +@@ -4660,8 +4663,10 @@ krb5_child_SOURCES = \ + src/sss_client/common.c \ + src/krb5_plugin/common/utils.c \ + src/krb5_plugin/idp/idp_utils.c \ +- src/krb5_plugin/passkey/passkey_utils.c \ + $(NULL) ++if BUILD_PASSKEY ++ krb5_child_SOURCES += src/krb5_plugin/passkey/passkey_utils.c ++endif # BUILD_PASSKEY + krb5_child_CFLAGS = \ + $(AM_CFLAGS) \ + $(POPT_CFLAGS) \ +diff --git a/src/providers/krb5/krb5_child.c b/src/providers/krb5/krb5_child.c +index a3d83b4c8c..7e43042bff 100644 +--- a/src/providers/krb5/krb5_child.c ++++ b/src/providers/krb5/krb5_child.c +@@ -999,6 +999,10 @@ static krb5_error_code answer_passkey(krb5_context kctx, + struct krb5_req *kr, + krb5_responder_context rctx) + { ++#ifndef BUILD_PASSKEY ++ DEBUG(SSSDBG_TRACE_FUNC, "Passkey auth not possible, SSSD built without passkey support!\n"); ++ return EINVAL; ++#else + enum sss_authtok_type type; + struct sss_passkey_message *msg; + struct sss_passkey_message *reply_msg = NULL; +@@ -1090,6 +1094,7 @@ static krb5_error_code answer_passkey(krb5_context kctx, + } + + return kerr; ++#endif /* BUILD_PASSKEY */ + } + + static krb5_error_code sss_krb5_responder(krb5_context ctx, diff --git a/SPECS/sssd.spec b/SPECS/sssd.spec index 8ee32e2..8d212a5 100644 --- a/SPECS/sssd.spec +++ b/SPECS/sssd.spec @@ -27,7 +27,7 @@ Name: sssd Version: 2.9.1 -Release: 4%{?dist}.1.alma.1 +Release: 4%{?dist}.5.alma.1 Summary: System Security Services Daemon License: GPLv3+ URL: https://github.com/SSSD/sssd/ @@ -48,6 +48,29 @@ Patch0005: 0005-Accept-krb5-1.21-for-building-the-PAC-plugin.patch Patch0006: 0006-MC-a-couple-of-additions-to-recover-from-invalid-memory.patch # https://github.com/SSSD/sssd/commit/b0212b04f109875936612a52a7b30a80e5a85ee5 Patch0007: 0007-SSS_CLIENT-replace-__thread-with-pthread_-specific.patch +# https://github.com/SSSD/sssd/commit/39cd0baa06742b349ed763aa40ea4de366e80f1a +Patch0008: 0008-DP-reduce-log-level-in-case-a-responder-asks.patch +# https://github.com/SSSD/sssd/commit/958a5e25c447dc502e8f8fbecf3253e62f92b0b2 +Patch0009: 0009-SSS_CLIENT-MC-in-case-mem-cache-file-validation-fails.patch +# https://github.com/SSSD/sssd/commit/0344c41aca0d6fcaa33e081ed77297607e48ced4 +Patch0010: 0010-SSS_CLIENT-check-if-mem-cache-fd-was-hijacked.patch +# https://github.com/SSSD/sssd/commit/2bcfb7f9238c27025e99e6445e9ba799e0bde7b8 +Patch0011: 0011-SSS_CLIENT-check-if-reponder-socket-was-hijacked.patch +# https://github.com/SSSD/sssd/commit/9b73614c49aeb3cfc3208dba5f472354086180b5 +Patch0012: 0012-LDAP-make-groups_by_user_send-recv-public.patch +# https://github.com/SSSD/sssd/commit/c02e09afe9610d872121708893db8a21fb201b12 +Patch0013: 0013-ad-gpo-evalute-host-groups.patch +# https://github.com/SSSD/sssd/commit/ff23e7e2879f94a907d05b615dbdb547aaa2e542 +Patch0014: 0014-sysdb-remove-sysdb_computer.ch.patch +# https://github.com/SSSD/sssd/commit/5f63d9bfc71b271844db1ee122172630be1afed0 +Patch0015: 0015-sdap-add-set_non_posix-parameter.patch +# https://github.com/SSSD/sssd/commit/7cf9a1ff0e876ea0970a3f0b3c389b87be834b4f +Patch0016: 0016-ipa-Add-BUILD_PASSKEY-conditional-for-passkey-codepath.patch +# https://github.com/SSSD/sssd/commit/eadee9a2a8f0dfe4f22c460537d6c87c493fa622 +Patch0017: 0017-pam-Conditionalize-passkey-code.patch +# https://github.com/SSSD/sssd/commit/a20dadc7ec9b21687356d1b0b0218db89f438c67 +Patch0018: 0018-Makefile-Respect-BUILD_PASSKEY-conditional.patch + ### Dependencies ### Requires: sssd-ad = %{version}-%{release} @@ -1073,6 +1096,19 @@ fi %systemd_postun_with_restart sssd.service %changelog +* Thu Jan 25 2024 Eduard Abdullin - 2.9.1-4.5.alma.1 +- Apply 0008-DP-reduce-log-level-in-case-a-responder-asks.patch +- Apply 0009-SSS_CLIENT-MC-in-case-mem-cache-file-validation-fails.patch +- Apply 0010-SSS_CLIENT-check-if-mem-cache-fd-was-hijacked.patch +- Apply 0011-SSS_CLIENT-check-if-reponder-socket-was-hijacked.patch +- Apply 0012-LDAP-make-groups_by_user_send-recv-public.patch +- Apply 0013-ad-gpo-evalute-host-groups.patch +- Apply 0014-sysdb-remove-sysdb_computer.ch.patch +- Apply 0015-sdap-add-set_non_posix-parameter.patch +- Apply 0016-ipa-Add-BUILD_PASSKEY-conditional-for-passkey-codepath.patch +- Apply 0017-pam-Conditionalize-passkey-code.patch +- Apply 0018-Makefile-Respect-BUILD_PASSKEY-conditional.patch + * Wed Dec 13 2023 Eduard Abdullin - 2.9.1-4.1.alma.1 - Apply 0007-SSS_CLIENT-replace-__thread-with-pthread_-specific.patch