From 46bae5a13bcbdaa9ebe48d5648c5a850dfa0b8c4 Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Fri, 4 Mar 2016 16:32:49 +0100 Subject: [PATCH 7/8] IPA: resolve PAC for trusted users on IPA clients --- src/providers/ipa/ipa_id.h | 9 ++ src/providers/ipa/ipa_s2n_exop.c | 181 +++++++++++++++++++++++++++++++++- src/providers/ipa/ipa_subdomains_id.c | 36 +++++++ 3 files changed, 225 insertions(+), 1 deletion(-) diff --git a/src/providers/ipa/ipa_id.h b/src/providers/ipa/ipa_id.h index 91a94115386955f63eca706bf6f4ac41884445eb..f59bc6a8e465501175fc4f6d50765c921575ad8f 100644 --- a/src/providers/ipa/ipa_id.h +++ b/src/providers/ipa/ipa_id.h @@ -120,4 +120,13 @@ ipa_initgr_get_overrides_send(TALLOC_CTX *memctx, struct ldb_message **groups, const char *groups_id_attr); int ipa_initgr_get_overrides_recv(struct tevent_req *req, int *dp_error); + +struct tevent_req *ipa_get_subdom_acct_process_pac_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sdap_handle *sh, + struct ipa_id_ctx *ipa_ctx, + struct sss_domain_info *dom, + struct ldb_message *user_msg); + +errno_t ipa_get_subdom_acct_process_pac_recv(struct tevent_req *req); #endif diff --git a/src/providers/ipa/ipa_s2n_exop.c b/src/providers/ipa/ipa_s2n_exop.c index 95af34a09d102b96b3a326f48de553ffdf61f23b..c1bc42ff14e7217eba258bbfa1a170dfee2ac972 100644 --- a/src/providers/ipa/ipa_s2n_exop.c +++ b/src/providers/ipa/ipa_s2n_exop.c @@ -22,11 +22,14 @@ #include "util/util.h" #include "util/sss_nss.h" #include "util/strtonum.h" -#include "db/sysdb.h" #include "providers/ldap/sdap_async_private.h" +#include "providers/ldap/sdap_async_ad.h" #include "providers/ldap/ldap_common.h" +#include "providers/ldap/sdap_idmap.h" #include "providers/ipa/ipa_id.h" #include "providers/ipa/ipa_subdomains.h" +#include "providers/ad/ad_pac.h" +#include "db/sysdb.h" enum input_types { INP_SID = 1, @@ -2401,3 +2404,179 @@ int ipa_s2n_get_acct_info_recv(struct tevent_req *req) return EOK; } + +struct ipa_get_subdom_acct_process_pac_state { + struct tevent_context *ev; + struct sdap_handle *sh; + struct sss_domain_info *dom; + char *username; + + size_t num_missing_sids; + char **missing_sids; + size_t num_cached_groups; + char **cached_groups; +}; + +static void ipa_get_subdom_acct_process_pac_done(struct tevent_req *subreq); + +struct tevent_req *ipa_get_subdom_acct_process_pac_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct sdap_handle *sh, + struct ipa_id_ctx *ipa_ctx, + struct sss_domain_info *dom, + struct ldb_message *user_msg) +{ + int ret; + struct ipa_get_subdom_acct_process_pac_state *state; + struct tevent_req *req; + struct tevent_req *subreq; + char *user_sid; + char *primary_group_sid; + size_t num_sids; + char **group_sids; + + req = tevent_req_create(mem_ctx, &state, + struct ipa_get_subdom_acct_process_pac_state); + if (req == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "tevent_req_create failed.\n"); + return NULL; + } + + state->ev = ev; + state->sh = sh; + state->dom = dom; + + ret = ad_get_pac_data_from_user_entry(state, user_msg, + ipa_ctx->sdap_id_ctx->opts->idmap_ctx->map, + &state->username, + &user_sid, &primary_group_sid, + &num_sids, &group_sids); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "ad_get_pac_data_from_user_entry failed.\n"); + goto done; + } + + ret = sdap_ad_tokengroups_get_posix_members(state, state->dom, + num_sids, group_sids, + &state->num_missing_sids, + &state->missing_sids, + &state->num_cached_groups, + &state->cached_groups); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "sdap_ad_tokengroups_get_posix_members failed.\n"); + goto done; + } + + + if (state->num_missing_sids == 0) { + ret = sdap_ad_tokengroups_update_members(state->username, + state->dom->sysdb, + state->dom, + state->cached_groups); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, "Membership update failed [%d]: %s\n", + ret, strerror(ret)); + } + + goto done; + } + + + subreq = ipa_s2n_get_list_send(state, state->ev, ipa_ctx, state->dom, + state->sh, + dp_opt_get_int(ipa_ctx->sdap_id_ctx->opts->basic, + SDAP_SEARCH_TIMEOUT), + BE_REQ_BY_SECID, REQ_FULL, REQ_INP_SECID, + state->missing_sids); + if (subreq == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "ipa_s2n_get_list_send failed.\n"); + ret = ENOMEM; + goto done; + } + tevent_req_set_callback(subreq, ipa_get_subdom_acct_process_pac_done, req); + + return req; + +done: + if (ret == EOK) { + tevent_req_done(req); + } else { + tevent_req_error(req, ret); + } + tevent_req_post(req, ev); + + return req; +} + +static void ipa_get_subdom_acct_process_pac_done(struct tevent_req *subreq) +{ + int ret; + struct tevent_req *req = tevent_req_callback_data(subreq, + struct tevent_req); + struct ipa_get_subdom_acct_process_pac_state *state = tevent_req_data(req, + struct ipa_get_subdom_acct_process_pac_state); + char **cached_groups; + size_t num_cached_groups; + + ret = ipa_s2n_get_list_recv(subreq); + talloc_zfree(subreq); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "s2n get_fqlist request failed.\n"); + tevent_req_error(req, ret); + return; + } + + /* from ad_pac.c */ + ret = sdap_ad_tokengroups_get_posix_members(state, state->dom, + state->num_missing_sids, + state->missing_sids, + NULL, NULL, + &num_cached_groups, + &cached_groups); + if (ret != EOK){ + DEBUG(SSSDBG_MINOR_FAILURE, + "sdap_ad_tokengroups_get_posix_members failed [%d]: %s\n", + ret, strerror(ret)); + goto done; + } + + state->cached_groups = concatenate_string_array(state, + state->cached_groups, + state->num_cached_groups, + cached_groups, + num_cached_groups); + if (state->cached_groups == NULL) { + ret = ENOMEM; + goto done; + } + + /* update membership of existing groups */ + ret = sdap_ad_tokengroups_update_members(state->username, + state->dom->sysdb, + state->dom, + state->cached_groups); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, "Membership update failed [%d]: %s\n", + ret, strerror(ret)); + goto done; + } + + ret = EOK; + +done: + if (ret == EOK) { + tevent_req_done(req); + } else { + tevent_req_error(req, ret); + } + + return; +} + +errno_t ipa_get_subdom_acct_process_pac_recv(struct tevent_req *req) +{ + TEVENT_REQ_RETURN_ON_ERROR(req); + + return EOK; +} diff --git a/src/providers/ipa/ipa_subdomains_id.c b/src/providers/ipa/ipa_subdomains_id.c index 70a1b6a12799b5a645bbf69f8cc19c30dcff82c5..f98f8bf8e28cc643b46e7ccfd6f559b3e85a7661 100644 --- a/src/providers/ipa/ipa_subdomains_id.c +++ b/src/providers/ipa/ipa_subdomains_id.c @@ -30,8 +30,10 @@ #include "db/sysdb.h" #include "providers/ldap/ldap_common.h" #include "providers/ldap/sdap_async.h" +#include "providers/ldap/sdap_async_ad.h" #include "providers/ipa/ipa_id.h" #include "providers/ad/ad_id.h" +#include "providers/ad/ad_pac.h" #include "providers/ipa/ipa_subdomains.h" static struct tevent_req * @@ -346,6 +348,8 @@ struct ipa_get_subdom_acct { int entry_type; const char *filter; int filter_type; + bool use_pac; + struct ldb_message *user_msg; int dp_error; }; @@ -372,6 +376,7 @@ struct tevent_req *ipa_get_subdom_acct_send(TALLOC_CTX *memctx, state->ctx = ipa_ctx->sdap_id_ctx; state->dp_error = DP_ERR_FATAL; state->override_attrs = override_attrs; + state->use_pac = false; state->op = sdap_id_op_create(state, state->ctx->conn->conn_cache); if (!state->op) { @@ -398,7 +403,15 @@ struct tevent_req *ipa_get_subdom_acct_send(TALLOC_CTX *memctx, case BE_REQ_GROUP: case BE_REQ_BY_SECID: case BE_REQ_USER_AND_GROUP: + ret = EOK; + break; case BE_REQ_INITGROUPS: + ret = check_if_pac_is_available(state, state->domain, ar, + &state->user_msg); + if (ret == EOK) { + state->use_pac = true; + } + ret = EOK; break; default: @@ -447,6 +460,29 @@ static void ipa_get_subdom_acct_connected(struct tevent_req *subreq) EXOP_SID2NAME_V1_OID)) { state->entry_type = BE_REQ_USER; } else { + if (state->use_pac && state->user_msg != NULL) { + /* This means the user entry is already in the cache and has + * the pac attached, we only have look up the missing groups + * and add the user to all groups. */ + + subreq = ipa_get_subdom_acct_process_pac_send(state, state->ev, + sdap_id_op_handle(state->op), + state->ipa_ctx, + state->domain, + state->user_msg); + if (subreq == NULL) { + DEBUG(SSSDBG_OP_FAILURE, + "ipa_get_subdom_acct_process_pac failed.\n"); + tevent_req_error(req, ENOMEM); + return; + } + tevent_req_set_callback(subreq, ipa_get_subdom_acct_done, req); + + return; + } + + /* Fall through if there is no PAC */ + DEBUG(SSSDBG_TRACE_FUNC, "Initgroups requests are not handled " \ "by the IPA provider but are resolved " \ "by the responder directly from the " \ -- 2.1.0