/*
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"
/* 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 %ld 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(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,
state->be_ctx->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_IMPORTANT_INFO, "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);
state->pd->pam_status = (ret == EOK) ? PAM_SUCCESS : 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() got more users than expected. "
"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 != 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;
}
/* 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));
goto done;
}
}
/* Notify FleetCommander that our side is done */
ret = ipa_pam_session_handler_notify_deskprofile_client(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 DBusConnection *
ipa_deskprofile_client_connect(void)
{
DBusConnection *conn;
DBusError error;
dbus_error_init(&error);
conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
if (dbus_error_is_set(&error)) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Unable to connect to the FleetCommanderClient bus [%s]: %s\n",
error.name, error.message);
conn = NULL;
goto done;
}
done:
dbus_error_free(&error);
return conn;
}
static errno_t
ipa_pam_session_handler_notify_deskprofile_client(uid_t uid,
const char *user_dir,
uint16_t prio)
{
DBusConnection *conn = NULL;
DBusMessage *msg = NULL;
DBusError error;
errno_t ret;
bool dbus_ret;
dbus_error_init(&error);
conn = ipa_deskprofile_client_connect();
if (conn == NULL) {
ret = EIO;
goto done;
}
msg = sbus_create_message(NULL,
SSS_FLEETCOMMANDERCLIENT_BUS,
SSS_FLEETCOMMANDERCLIENT_PATH,
SSS_FLEETCOMMANDERCLIENT_IFACE,
"ProcessSSSDFiles",
DBUS_TYPE_UINT32, &uid,
DBUS_TYPE_STRING, &user_dir,
DBUS_TYPE_UINT16, &prio);
if (msg == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create D-Bus Message!\n");
ret = ENOMEM;
goto done;
}
dbus_ret = dbus_connection_send(conn, msg, NULL);
if (dbus_ret == FALSE) {
ret = EIO;
goto done;
}
ret = EOK;
done:
if (msg != NULL) {
dbus_message_unref(msg);
}
if (conn != NULL) {
dbus_connection_unref(conn);
}
return ret;
}