diff options
Diffstat (limited to 'src/providers/ipa/ipa_session.c')
-rw-r--r-- | src/providers/ipa/ipa_session.c | 861 |
1 files changed, 861 insertions, 0 deletions
diff --git a/src/providers/ipa/ipa_session.c b/src/providers/ipa/ipa_session.c new file mode 100644 index 0000000..bcd8055 --- /dev/null +++ b/src/providers/ipa/ipa_session.c @@ -0,0 +1,861 @@ +/* + SSSD + + IPA Backend Module -- Session Management + + Authors: + Fabiano FidĂȘncio <fidencio@redhat.com> + + Copyright (C) 2017 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 <http://www.gnu.org/licenses/>. +*/ +#include <security/pam_modules.h> + +#include "util/child_common.h" +#include "providers/ldap/sdap_async.h" +#include "providers/ipa/ipa_common.h" +#include "providers/ipa/ipa_config.h" +#include "providers/ipa/ipa_hosts.h" +#include "providers/ipa/ipa_subdomains.h" +#include "providers/ipa/ipa_session.h" +#include "providers/ipa/ipa_rules_common.h" +#include "providers/ipa/ipa_deskprofile_private.h" +#include "providers/ipa/ipa_deskprofile_config.h" +#include "providers/ipa/ipa_deskprofile_rules.h" +#include "providers/ipa/ipa_deskprofile_rules_util.h" +#include "sss_iface/sss_iface_async.h" + + +/* Those here are used for sending a message to the deskprofile client + * informing that our side is done. */ +#define SSS_FLEETCOMMANDERCLIENT_BUS "org.freedesktop.FleetCommanderClient" +#define SSS_FLEETCOMMANDERCLIENT_PATH "/org/freedesktop/FleetCommanderClient" +#define SSS_FLEETCOMMANDERCLIENT_IFACE "org.freedesktop.FleetCommanderClient" + +#define MINUTE_IN_SECONDS 60 + +struct ipa_fetch_deskprofile_state { + struct tevent_context *ev; + struct be_ctx *be_ctx; + struct sdap_id_ctx *sdap_ctx; + struct ipa_session_ctx *session_ctx; + struct sdap_id_op *sdap_op; + struct dp_option *ipa_options; + struct sdap_search_base **search_bases; + const char *username; + + /* Hosts */ + struct ipa_common_entries *hosts; + struct sysdb_attrs *ipa_host; + + /* Rules */ + struct ipa_common_entries *rules; + struct sysdb_attrs *config; + uint16_t priority; +}; + +static errno_t ipa_fetch_deskprofile_retry(struct tevent_req *req); +static void ipa_fetch_deskprofile_connect_done(struct tevent_req *subreq); +static errno_t ipa_fetch_deskprofile_hostinfo(struct tevent_req *req); +static void ipa_fetch_deskprofile_hostinfo_done(struct tevent_req *subreq); +static void ipa_fetch_deskprofile_config_done(struct tevent_req *subreq); +static void ipa_fetch_deskprofile_rules_done(struct tevent_req *subreq); + +static struct tevent_req * +ipa_fetch_deskprofile_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct be_ctx *be_ctx, + struct ipa_session_ctx *session_ctx, + const char *username) +{ + struct ipa_fetch_deskprofile_state *state; + struct tevent_req *req; + time_t now; + time_t refresh_interval; + time_t request_interval; + time_t next_request; + bool offline; + errno_t ret; + + req = tevent_req_create(mem_ctx, &state, + struct ipa_fetch_deskprofile_state); + if (req == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); + return NULL; + } + + state->ev = ev; + state->be_ctx = be_ctx; + state->session_ctx = session_ctx; + state->sdap_ctx = session_ctx->sdap_ctx; + state->ipa_options = session_ctx->ipa_options; + state->search_bases = session_ctx->deskprofile_search_bases; + state->username = username; + state->hosts = talloc_zero(state, struct ipa_common_entries); + if (state->hosts == NULL) { + ret = ENOMEM; + goto immediately; + } + state->rules = talloc_zero(state, struct ipa_common_entries); + if (state->rules == NULL) { + ret = ENOMEM; + goto immediately; + } + + if (state->search_bases == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "No Desktop Profile search base found.\n"); + ret = EINVAL; + goto immediately; + } + + state->sdap_op = sdap_id_op_create(state, + state->sdap_ctx->conn->conn_cache); + if (state->sdap_op == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "sdap_id_op_create() failed\n"); + ret = ENOMEM; + goto immediately; + } + + now = time(NULL); + + request_interval = dp_opt_get_int(state->ipa_options, + IPA_DESKPROFILE_REQUEST_INTERVAL); + /* This value is in minutes ... */ + request_interval *= MINUTE_IN_SECONDS; + + if (state->session_ctx->no_rules_found && + now < session_ctx->last_request + request_interval) { + next_request = (session_ctx->last_request + request_interval - now); + /* This value is in seconds ... */ + next_request /= 60; + DEBUG(SSSDBG_TRACE_FUNC, + "No rules were found in the last request.\n" + "Next request will happen in any login after %"SPRItime" minutes\n", + next_request); + ret = ENOENT; + goto immediately; + } + + state->session_ctx->no_rules_found = false; + + offline = be_is_offline(be_ctx); + DEBUG(SSSDBG_TRACE_ALL, "Connection status is [%s].\n", + offline ? "offline" : "online"); + + refresh_interval = dp_opt_get_int(state->ipa_options, + IPA_DESKPROFILE_REFRESH); + + if (offline || now < session_ctx->last_update + refresh_interval) { + DEBUG(SSSDBG_TRACE_FUNC, + "Performing cached Desktop Profile evaluation\n"); + ret = EOK; + goto immediately; + } + + ret = ipa_fetch_deskprofile_retry(req); + if (ret != EAGAIN) { + goto immediately; + } + + return req; + +immediately: + if (ret == EOK) { + tevent_req_done(req); + } else { + tevent_req_error(req, ret); + } + tevent_req_post(req, ev); + + return req; +} + +static errno_t +ipa_fetch_deskprofile_retry(struct tevent_req *req) +{ + struct tevent_req *subreq; + struct ipa_fetch_deskprofile_state *state; + int ret; + + state = tevent_req_data(req, struct ipa_fetch_deskprofile_state); + + subreq = sdap_id_op_connect_send(state->sdap_op, state, &ret); + if (subreq == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, + "sdap_id_op_connect_send() failed: %d (%s)\n", + ret, strerror(ret)); + + return ret; + } + + tevent_req_set_callback(subreq, ipa_fetch_deskprofile_connect_done, req); + + return EAGAIN; +} + +static void +ipa_fetch_deskprofile_connect_done(struct tevent_req *subreq) +{ + struct tevent_req *req = NULL; + int dp_error; + errno_t ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); + + ret = sdap_id_op_connect_recv(subreq, &dp_error); + talloc_zfree(subreq); + if (ret != EOK) { + goto done; + } + + ret = ipa_fetch_deskprofile_hostinfo(req); + if (ret == EAGAIN) { + return; + } + +done: + if (ret == EOK) { + tevent_req_done(req); + } else { + tevent_req_error(req, ret); + } +} + +static errno_t +ipa_fetch_deskprofile_hostinfo(struct tevent_req *req) +{ + struct tevent_req *subreq; + struct ipa_fetch_deskprofile_state *state; + const char *hostname; + + state = tevent_req_data(req, struct ipa_fetch_deskprofile_state); + hostname = dp_opt_get_string(state->ipa_options, IPA_HOSTNAME); + + subreq = ipa_host_info_send(state, + state->ev, + sdap_id_op_handle(state->sdap_op), + state->sdap_ctx->opts, + hostname, + state->session_ctx->host_map, + state->session_ctx->hostgroup_map, + state->session_ctx->host_search_bases); + if (subreq == NULL) { + return ENOMEM; + } + + tevent_req_set_callback(subreq, ipa_fetch_deskprofile_hostinfo_done, req); + + return EAGAIN; +} + +static void +ipa_fetch_deskprofile_hostinfo_done(struct tevent_req *subreq) +{ + struct tevent_req *req; + struct ipa_fetch_deskprofile_state *state; + errno_t ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct ipa_fetch_deskprofile_state); + + ret = ipa_host_info_recv(subreq, state, + &state->hosts->entry_count, + &state->hosts->entries, + &state->hosts->group_count, + &state->hosts->groups); + state->hosts->entry_subdir = DESKPROFILE_HOSTS_SUBDIR; + state->hosts->group_subdir = DESKPROFILE_HOSTGROUPS_SUBDIR; + talloc_zfree(subreq); + if (ret != EOK) { + goto done; + } + + ret = ipa_get_host_attrs(state->ipa_options, + state->hosts->entry_count, + state->hosts->entries, + &state->ipa_host); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Could not locate IPA host.\n"); + goto done; + } + + subreq = ipa_deskprofile_get_config_send(state, + state->ev, + sdap_id_op_handle(state->sdap_op), + state->sdap_ctx->opts, + state->ipa_options); + if (subreq == NULL) { + ret = ENOMEM; + goto done; + } + + tevent_req_set_callback(subreq, ipa_fetch_deskprofile_config_done, req); + return; + +done: + tevent_req_error(req, ret); +} + +static void +ipa_fetch_deskprofile_config_done(struct tevent_req *subreq) +{ + struct tevent_req *req; + struct ipa_fetch_deskprofile_state *state; + errno_t ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct ipa_fetch_deskprofile_state); + + ret = ipa_deskprofile_get_config_recv(subreq, state, &state->config); + talloc_zfree(subreq); + if (ret != EOK) { + goto done; + } + + ret = sysdb_store_custom(state->be_ctx->domain, IPA_DESKPROFILE_PRIORITY, + DESKPROFILE_CONFIG_SUBDIR, state->config); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to save Desktop Profile policy\n"); + goto done; + } + + subreq = ipa_deskprofile_rule_info_send(state, + state->ev, + sdap_id_op_handle(state->sdap_op), + state->sdap_ctx->opts, + state->search_bases, + state->ipa_host, + state->be_ctx->domain, + state->username); + if (subreq == NULL) { + ret = ENOMEM; + goto done; + } + + tevent_req_set_callback(subreq, ipa_fetch_deskprofile_rules_done, req); + return; + +done: + tevent_req_error(req, ret); +} + +static void +ipa_fetch_deskprofile_rules_done(struct tevent_req *subreq) +{ + struct tevent_req *req; + struct ipa_fetch_deskprofile_state *state; + int dp_error; + errno_t ret; + bool found; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct ipa_fetch_deskprofile_state); + + ret = ipa_deskprofile_rule_info_recv(subreq, + state, + &state->rules->entry_count, + &state->rules->entries); + state->rules->entry_subdir = DESKPROFILE_RULES_SUBDIR; + talloc_zfree(subreq); + if (ret == ENOENT) { + /* Set ret to EOK so we can safely call sdap_id_op_done. */ + ret = EOK; + found = false; + } else if (ret == EOK) { + found = true; + } else { + goto done; + } + + ret = sdap_id_op_done(state->sdap_op, ret, &dp_error); + if (dp_error == DP_ERR_OK && ret != EOK) { + /* retry */ + ret = ipa_fetch_deskprofile_retry(req); + if (ret != EAGAIN) { + tevent_req_error(req, ret); + } + return; + } else if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + + /* For now, let's completely purge the previous stored + * rules before saving the new ones */ + ret = ipa_common_purge_rules(state->be_ctx->domain, + DESKPROFILE_RULES_SUBDIR); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Unable to remove Desktop Profile rules\n"); + goto done; + } + + if (!found) { + ret = ENOENT; + goto done; + } + + ret = ipa_common_save_rules(state->be_ctx->domain, + state->hosts, NULL, state->rules, + &state->session_ctx->last_update); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to save Desktop Profile rules\n"); + goto done; + } + + ret = EOK; + +done: + if (ret != EOK) { + tevent_req_error(req, ret); + return; + } + + tevent_req_done(req); +} + +static errno_t +ipa_fetch_deskprofile_recv(struct tevent_req *req) +{ + TEVENT_REQ_RETURN_ON_ERROR(req); + + return EOK; +} + +struct ipa_pam_session_handler_state { + struct tevent_context *ev; + struct be_ctx *be_ctx; + struct ipa_session_ctx *session_ctx; + struct pam_data *pd; + + /* Those attributes are used for: + * - saving the deskprofile rules to the disk; + * - deleting the deskprofile rules from the disk; + * - contacting the deskprofile client that everything is ready; + */ + char *shortname; + char *domain; + char *user_dir; + uid_t uid; + gid_t gid; +}; + +static errno_t +ipa_pam_session_handler_get_deskprofile_user_info( + TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + const char *username, + char **_shortname, + char **_domain, + char **_user_dir, + uid_t *uid, + gid_t *gid); +static void ipa_pam_session_handler_done(struct tevent_req *subreq); +static errno_t +ipa_pam_session_handler_save_deskprofile_rules( + struct be_ctx *be_ctx, + struct sss_domain_info *domain, + const char *username, /* fully-qualified */ + const char *user_dir, + const char *hostname, + uid_t uid, + gid_t gid); +static errno_t +ipa_pam_session_handler_notify_deskprofile_client(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + uid_t uid, + const char *user_dir, + uint16_t prio); + + +struct tevent_req * +ipa_pam_session_handler_send(TALLOC_CTX *mem_ctx, + struct ipa_session_ctx *session_ctx, + struct pam_data *pd, + struct dp_req_params *params) +{ + struct tevent_req *req; + struct tevent_req *subreq; + struct ipa_pam_session_handler_state *state; + errno_t ret; + + DEBUG(SSSDBG_TRACE_FUNC, "Retrieving Desktop Profile rules\n"); + req = tevent_req_create(mem_ctx, &state, + struct ipa_pam_session_handler_state); + if (req == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "tevent_req_create() failed\n"); + return NULL; + } + + state->pd = pd; + state->ev = params->ev; + state->be_ctx = params->be_ctx; + state->session_ctx = session_ctx; + + /* Get all the user info that will be needed in order the delete the + * user's deskprofile directory from the disk, create the user's directory, + * save the fetched rules to the disk and notify the deskprofile client + * that this operation is done. */ + ret = ipa_pam_session_handler_get_deskprofile_user_info( + state, + params->domain, + pd->user, + &state->shortname, + &state->domain, + &state->user_dir, + &state->uid, + &state->gid); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "ipa_deskprofile_get_user_info() failed [%d]: %s\n", + ret, sss_strerror(ret)); + state->pd->pam_status = PAM_SESSION_ERR; + goto done; + } + + /* As no proper merging mechanism has been implemented yet ... + * let's just remove the user directory stored in the disk as it's + * going to be created again in case there's any rule fetched. */ + ret = ipa_deskprofile_rules_remove_user_dir(state->user_dir, + state->uid, + state->gid); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "ipa_deskprofile_rules_remove_user_dir() failed.\n"); + state->pd->pam_status = PAM_SESSION_ERR; + goto done; + } + + subreq = ipa_fetch_deskprofile_send(state, state->ev, state->be_ctx, + state->session_ctx, pd->user); + if (subreq == NULL) { + state->pd->pam_status = PAM_SESSION_ERR; + goto done; + } + + tevent_req_set_callback(subreq, ipa_pam_session_handler_done, req); + return req; + +done: + tevent_req_done(req); + tevent_req_post(req, params->ev); + + return req; +} + +static void +ipa_pam_session_handler_done(struct tevent_req *subreq) +{ + struct tevent_req *req; + struct ipa_pam_session_handler_state *state; + const char *hostname; + errno_t ret; + + req = tevent_req_callback_data(subreq, struct tevent_req); + state = tevent_req_data(req, struct ipa_pam_session_handler_state); + + ret = ipa_fetch_deskprofile_recv(subreq); + talloc_free(subreq); + + if (ret == ENOENT) { + 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); + } + state->pd->pam_status = PAM_SUCCESS; + goto done; + } else if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Unable to fetch Desktop Profile rules [%d]: %s\n", + ret, sss_strerror(ret)); + state->pd->pam_status = PAM_SYSTEM_ERR; + goto done; + } + + state->session_ctx->last_request = time(NULL); + + hostname = dp_opt_get_string(state->session_ctx->ipa_options, IPA_HOSTNAME); + ret = ipa_pam_session_handler_save_deskprofile_rules(state->be_ctx, + state->be_ctx->domain, + state->pd->user, + state->user_dir, + hostname, + state->uid, + state->gid); + + if (ret == EOK || ret == ENOENT) { + state->pd->pam_status = PAM_SUCCESS; + } else { + state->pd->pam_status = PAM_SESSION_ERR; + } + +done: + /* TODO For backward compatibility we always return EOK to DP now. */ + tevent_req_done(req); +} + +errno_t +ipa_pam_session_handler_recv(TALLOC_CTX *mem_ctx, + struct tevent_req *req, + struct pam_data **_data) +{ + struct ipa_pam_session_handler_state *state = NULL; + + state = tevent_req_data(req, struct ipa_pam_session_handler_state); + + TEVENT_REQ_RETURN_ON_ERROR(req); + + *_data = talloc_steal(mem_ctx, state->pd); + + return EOK; +} + +static errno_t +ipa_pam_session_handler_get_deskprofile_user_info(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domain, + const char *username, + char **_shortname, + char **_domain, + char **_user_dir, + uid_t *_uid, + gid_t *_gid) +{ + TALLOC_CTX *tmp_ctx; + struct ldb_result *res = NULL; + char *shortname; + char *domain_name; + char *user_dir; + uid_t uid; + gid_t gid; + errno_t ret; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + ret = sss_parse_internal_fqname(tmp_ctx, username, + &shortname, &domain_name); + if (ret != EOK) { + DEBUG(SSSDBG_TRACE_FUNC, "Failed to parse \"%s\" [%d]: %s\n", + username, ret, sss_strerror(ret)); + goto done; + } + + user_dir = talloc_asprintf(tmp_ctx, IPA_DESKPROFILE_RULES_USER_DIR"/%s/%s", + domain_name, shortname); + if (user_dir == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf() failed!\n"); + ret = ENOMEM; + goto done; + } + + ret = sysdb_getpwnam(tmp_ctx, domain, username, &res); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_getpwnam() failed [%d]: %s\n", + ret, sss_strerror(ret)); + goto done; + } + + if (res->count != 1) { + DEBUG(SSSDBG_CRIT_FAILURE, + "sysdb_getpwnam() returned unexpected amount of users. " + "Expected [%d], got [%d]\n", 1, res->count); + ret = EINVAL; + goto done; + } + + uid = ldb_msg_find_attr_as_uint64(res->msgs[0], SYSDB_UIDNUM, 0); + gid = ldb_msg_find_attr_as_uint64(res->msgs[0], SYSDB_GIDNUM, 0); + if (uid == 0 || gid == 0) { + /* As IPA doesn't handle root users ou groups, we know for sure that's + * something wrong in case we get uid = 0 or gid = 0. + */ + ret = EINVAL; + goto done; + } + + ret = EOK; + + *_shortname = talloc_steal(mem_ctx, shortname); + *_domain = talloc_steal(mem_ctx, domain_name); + *_user_dir = talloc_steal(mem_ctx, user_dir); + *_uid = uid; + *_gid = gid; + +done: + talloc_free(tmp_ctx); + return ret; +} + +static errno_t +ipa_pam_session_handler_save_deskprofile_rules( + struct be_ctx *be_ctx, + struct sss_domain_info *domain, + const char *username, /* fully-qualified */ + const char *user_dir, + const char *hostname, + uid_t uid, + gid_t gid) +{ + TALLOC_CTX *tmp_ctx; + const char **attrs_get_cached_rules; + size_t rule_count; + struct sysdb_attrs **rules; + uint16_t priority; + errno_t ret; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + /* Get Desktop Profile priority from sysdb */ + ret = deskprofile_get_cached_priority(be_ctx->domain, &priority); + if (ret == ENOENT) { + DEBUG(SSSDBG_FUNC_DATA, "No Desktop Profile priority found in sysdb\n"); + goto done; + } else if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "deskprofile_get_cached_priority() failed [%d]: %s\n", + ret, sss_strerror(ret)); + goto done; + } + + + /* Get Desktop Profile rules from sysdb */ + attrs_get_cached_rules = deskprofile_get_attrs_to_get_cached_rules(tmp_ctx); + if (attrs_get_cached_rules == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, + "deskprofile_get_attrs_get_cached_rules() failed\n"); + ret = ENOMEM; + goto done; + } + ret = ipa_common_get_cached_rules(tmp_ctx, be_ctx->domain, + IPA_DESKPROFILE_RULE, + DESKPROFILE_RULES_SUBDIR, + attrs_get_cached_rules, + &rule_count, + &rules); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Could not retrieve Desktop Profile rules from the cache\n"); + goto done; + } + + /* nothing to do for FC */ + if (!rule_count) { + DEBUG(SSSDBG_FUNC_DATA, "No Desktop Profile rules found in sysdb\n"); + ret = ENOENT; + goto done; + } + + /* Create the user directory where the rules are going to be stored */ + ret = ipa_deskprofile_rules_create_user_dir(username, uid, gid); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Cannot create the user directory [%d]: %s\n", + ret, sss_strerror(ret)); + goto done; + } + + /* Save the rules to the disk */ + for (size_t i = 0; i < rule_count; i++) { + ret = ipa_deskprofile_rules_save_rule_to_disk(tmp_ctx, + priority, + rules[i], + domain, + hostname, + username, + uid, + gid); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Failed to save a Desktop Profile Rule to disk [%d]: %s\n", + ret, sss_strerror(ret)); + continue; + } + } + + /* Notify FleetCommander that our side is done */ + ret = ipa_pam_session_handler_notify_deskprofile_client(be_ctx, + be_ctx->ev, + uid, + user_dir, + priority); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, + "ipa_pam_session_handler_notify_deskprofile_client() " + "failed [%d]: %s\n", + ret, sss_strerror(ret)); + goto done; + } + + ret = EOK; + +done: + talloc_free(tmp_ctx); + return ret; +} + +static void +ipa_pam_session_handler_notify_deskprofile_client_done(struct tevent_req *subreq); + +static errno_t +ipa_pam_session_handler_notify_deskprofile_client(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + uid_t uid, + const char *user_dir, + uint16_t prio) +{ + struct sbus_connection *conn; + struct tevent_req *subreq; + + conn = sbus_connect_system(mem_ctx, ev, NULL, NULL); + if (conn == NULL) { + return ENOMEM; + } + + subreq = sbus_call_fleet_ProcessSSSDFiles_send(mem_ctx, conn, + SSS_FLEETCOMMANDERCLIENT_BUS, SSS_FLEETCOMMANDERCLIENT_PATH, + uid, user_dir, prio); + if (subreq == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create subrequest!\n"); + talloc_free(conn); + return ENOMEM; + } + + tevent_req_set_callback(subreq, ipa_pam_session_handler_notify_deskprofile_client_done, + conn); + + return EOK; +} + +static void ipa_pam_session_handler_notify_deskprofile_client_done(struct tevent_req *subreq) +{ + struct sbus_connection *conn; + errno_t ret; + + conn = tevent_req_callback_data(subreq, struct sbus_connection); + + ret = sbus_call_fleet_ProcessSSSDFiles_recv(subreq); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "Error sending sbus message [%d]: %s\n", + ret, sss_strerror(ret)); + } + + talloc_free(conn); +} |