ifp_components.c revision 62ebed8582285bd24efba92b9a06366511507946
/*
Authors:
Pavel Březina <pbrezina@redhat.com>
Copyright (C) 2014 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 <string.h>
#include <talloc.h>
#include <signal.h>
#include <errno.h>
#include <utime.h>
#include "config.h"
#include "confdb/confdb.h"
#include "util/util.h"
#include "responder/common/responder.h"
#include "responder/ifp/ifp_components.h"
#ifdef HAVE_CONFIG_LIB
#include "util/sss_config.h"
#endif
#define PATH_MONITOR IFP_PATH_COMPONENTS "/monitor"
#define PATH_RESPONDERS IFP_PATH_COMPONENTS "/Responders"
#define PATH_BACKENDS IFP_PATH_COMPONENTS "/Backends"
enum component_type {
COMPONENT_MONITOR,
COMPONENT_RESPONDER,
COMPONENT_BACKEND
};
static bool responder_exists(const char *name)
{
const char * const *svc = get_known_services();
int i;
for (i = 0; svc[i] != NULL; i++) {
if (strcmp(svc[i], name) == 0) {
return true;
}
}
return false;
}
static bool backend_exists(struct confdb_ctx *confdb, const char *name)
{
char **names = NULL;
errno_t ret;
int i;
ret = confdb_list_all_domain_names(NULL, confdb, &names);
if (ret != EOK) {
return false;
}
for (i = 0; names[i] != NULL; i++) {
if (strcmp(names[i], name) == 0) {
return true;
}
}
return false;
}
static errno_t check_and_get_component_from_path(TALLOC_CTX *mem_ctx,
struct confdb_ctx *confdb,
const char *path,
enum component_type *_type,
char **_name)
{
enum component_type type;
char *name = NULL;
errno_t ret;
if (confdb == NULL || path == NULL) {
return EINVAL;
}
if (strcmp(path, PATH_MONITOR) == 0) {
type = COMPONENT_MONITOR;
name = talloc_strdup(mem_ctx, "monitor");
if (name == NULL) {
ret = ENOMEM;
goto done;
}
} else {
name = sbus_opath_get_object_name(mem_ctx, path, PATH_RESPONDERS);
if (name != NULL) {
type = COMPONENT_RESPONDER;
} else {
name = sbus_opath_get_object_name(mem_ctx, path, PATH_BACKENDS);
if (name != NULL) {
type = COMPONENT_BACKEND;
} else {
ret = EINVAL;
goto done;
}
}
}
if (strchr(name, '/') != NULL) {
ret = EINVAL;
goto done;
}
switch (type) {
case COMPONENT_MONITOR:
/* noop */
break;
case COMPONENT_RESPONDER:
if (!responder_exists(name)) {
ret = ENOENT;
goto done;
}
break;
case COMPONENT_BACKEND:
if (!backend_exists(confdb, name)) {
ret = ENOENT;
goto done;
}
break;
}
if (_type != NULL) {
*_type = type;
}
if (_name != NULL) {
*_name = name;
}
ret = EOK;
done:
if (ret != EOK) {
talloc_free(name);
}
return ret;
}
static errno_t change_debug_level_tmp(struct confdb_ctx *confdb,
const char *name,
enum component_type type,
uint32_t level)
{
TALLOC_CTX *tmp_ctx = NULL;
const char *confdb_path = NULL;
const char **values = NULL;
errno_t ret;
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
return ENOMEM;
}
switch (type) {
case COMPONENT_MONITOR:
confdb_path = CONFDB_MONITOR_CONF_ENTRY;
break;
case COMPONENT_RESPONDER:
confdb_path = talloc_asprintf(tmp_ctx, CONFDB_SERVICE_PATH_TMPL, name);
break;
case COMPONENT_BACKEND:
confdb_path = talloc_asprintf(tmp_ctx, CONFDB_DOMAIN_PATH_TMPL, name);
break;
}
if (confdb_path == NULL) {
ret = ENOMEM;
goto done;
}
values = talloc_zero_array(tmp_ctx, const char*, 2);
if (values == NULL) {
ret = ENOMEM;
goto done;
}
values[0] = talloc_asprintf(tmp_ctx, "0x%.4x", level);
if (values[0] == NULL) {
ret = ENOMEM;
goto done;
}
ret = confdb_add_param(confdb, true, confdb_path,
CONFDB_SERVICE_DEBUG_LEVEL, values);
if (ret != EOK) {
goto done;
}
/* reload the configuration */
if (kill(getppid(), SIGHUP) != 0) {
ret = errno;
goto done;
}
ret = EOK;
done:
talloc_free(tmp_ctx);
return ret;
}
static errno_t list_responders(TALLOC_CTX *mem_ctx,
const char ***_list,
int *_num)
{
const char **list = NULL;
const char * const *svc = get_known_services();
errno_t ret;
int num;
int i;
for (num = 0; svc[num] != NULL; num++);
list = talloc_array(mem_ctx, const char*, num);
if (list == NULL) {
ret = ENOMEM;
goto done;
}
for (i = 0; i < num; i++) {
list[i] = sbus_opath_compose(list, PATH_RESPONDERS, svc[i]);
if (list[i] == NULL) {
ret = ENOMEM;
goto done;
}
}
*_num = num;
*_list = list;
ret = EOK;
done:
if (ret != EOK) {
talloc_free(list);
}
return ret;
}
static errno_t list_backends(TALLOC_CTX *mem_ctx,
struct confdb_ctx *confdb,
const char ***_list,
int *_num)
{
TALLOC_CTX *tmp_ctx = NULL;
const char **list = NULL;
char **names = NULL;
errno_t ret;
int num;
int i;
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
return ENOMEM;
}
ret = confdb_list_all_domain_names(tmp_ctx, confdb, &names);
if (ret != EOK) {
goto done;
}
for (num = 0; names[num] != NULL; num++);
list = talloc_array(tmp_ctx, const char*, num);
if (list == NULL) {
ret = ENOMEM;
goto done;
}
for (i = 0; i < num; i++) {
list[i] = sbus_opath_compose(list, PATH_BACKENDS, names[i]);
if (list[i] == NULL) {
ret = ENOMEM;
goto done;
}
}
*_num = num;
*_list = talloc_steal(mem_ctx, list);
ret = EOK;
done:
talloc_free(tmp_ctx);
return ret;
}
int ifp_list_components(struct sbus_request *dbus_req, void *data)
{
struct ifp_ctx *ctx = NULL;
DBusError *error = NULL;
const char **responders = NULL;
const char **backends = NULL;
const char **result = NULL;
int num_responders;
int num_backends;
int num;
int i;
errno_t ret;
ctx = talloc_get_type(data, struct ifp_ctx);
if (ctx == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Invalid ifp context!\n");
ret = EINVAL;
goto done;
}
ret = list_responders(dbus_req, &responders, &num_responders);
if (ret != EOK) {
goto done;
}
ret = list_backends(dbus_req, ctx->rctx->cdb, &backends, &num_backends);
if (ret != EOK) {
goto done;
}
num = num_responders + num_backends + 1;
result = talloc_array(dbus_req, const char*, num);
if (result == NULL) {
ret = ENOMEM;
goto done;
}
result[0] = PATH_MONITOR;
for (i = 0; i < num_responders; i++) {
result[i + 1] = talloc_steal(result, responders[i]);
}
for (i = 0; i < num_backends; i++) {
result[i + num_responders + 1] = talloc_steal(result, backends[i]);
}
ret = EOK;
done:
if (ret != EOK) {
error = sbus_error_new(dbus_req, DBUS_ERROR_FAILED,
"%s", strerror(ret));
return sbus_request_fail_and_finish(dbus_req, error);
}
return iface_ifp_ListComponents_finish(dbus_req, result, num);
}
int ifp_list_responders(struct sbus_request *dbus_req, void *data)
{
DBusError *error = NULL;
const char **result = NULL;
int num;
errno_t ret;
ret = list_responders(dbus_req, &result, &num);
if (ret != EOK) {
error = sbus_error_new(dbus_req, DBUS_ERROR_FAILED,
"%s", strerror(ret));
return sbus_request_fail_and_finish(dbus_req, error);
}
return iface_ifp_ListResponders_finish(dbus_req, result, num);
}
int ifp_list_backends(struct sbus_request *dbus_req, void *data)
{
struct ifp_ctx *ctx = NULL;
DBusError *error = NULL;
const char **result = NULL;
int num;
errno_t ret;
ctx = talloc_get_type(data, struct ifp_ctx);
if (ctx == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Invalid ifp context!\n");
ret = EINVAL;
goto done;
}
ret = list_backends(dbus_req, ctx->rctx->cdb, &result, &num);
done:
if (ret != EOK) {
error = sbus_error_new(dbus_req, DBUS_ERROR_FAILED,
"%s", strerror(ret));
return sbus_request_fail_and_finish(dbus_req, error);
}
return iface_ifp_ListBackends_finish(dbus_req, result, num);
}
int ifp_find_monitor(struct sbus_request *dbus_req, void *data)
{
return iface_ifp_FindMonitor_finish(dbus_req, PATH_MONITOR);
}
int ifp_find_responder_by_name(struct sbus_request *dbus_req,
void *data,
const char *arg_name)
{
DBusError *error = NULL;
const char *result = NULL;
if (responder_exists(arg_name)) {
result = sbus_opath_compose(dbus_req, PATH_RESPONDERS, arg_name);
if (result == NULL) {
return sbus_request_fail_and_finish(dbus_req, NULL);
}
} else {
error = sbus_error_new(dbus_req, DBUS_ERROR_FAILED,
"Responder \"%s\" does not exist", arg_name);
return sbus_request_fail_and_finish(dbus_req, error);
}
return iface_ifp_FindResponderByName_finish(dbus_req, result);
}
int ifp_find_backend_by_name(struct sbus_request *dbus_req,
void *data,
const char *arg_name)
{
struct ifp_ctx *ctx = NULL;
DBusError *error = NULL;
const char *result = NULL;
ctx = talloc_get_type(data, struct ifp_ctx);
if (ctx == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Invalid ifp context!\n");
error = sbus_error_new(dbus_req, DBUS_ERROR_FAILED,
"%s\n", strerror(EINVAL));
return sbus_request_fail_and_finish(dbus_req, error);
}
if (backend_exists(ctx->rctx->cdb, arg_name)) {
result = sbus_opath_compose(dbus_req, PATH_BACKENDS, arg_name);
if (result == NULL) {
return sbus_request_fail_and_finish(dbus_req, NULL);
}
} else {
error = sbus_error_new(dbus_req, DBUS_ERROR_FAILED,
"Backend \"%s\" does not exist", arg_name);
return sbus_request_fail_and_finish(dbus_req, error);
}
return iface_ifp_FindBackendByName_finish(dbus_req, result);
}
int ifp_component_enable(struct sbus_request *dbus_req, void *data)
{
#ifndef HAVE_CONFIG_LIB
return sbus_request_fail_and_finish(dbus_req,
sbus_error_new(dbus_req, DBUS_ERROR_NOT_SUPPORTED, NULL));
#else
struct ifp_ctx *ctx = NULL;
DBusError *error = NULL;
const char *path = dbus_message_get_path(dbus_req->message);
char *name = NULL;
enum component_type type;
struct sss_config_ctx *config_ctx = NULL;
errno_t ret;
ctx = talloc_get_type(data, struct ifp_ctx);
if (ctx == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Invalid ifp context!\n");
ret = EINVAL;
goto done;
}
ret = check_and_get_component_from_path(dbus_req, ctx->rctx->cdb,
path, &type, &name);
if (ret != EOK) {
goto done;
}
config_ctx = sss_config_open(dbus_req, NULL, CONFDB_DEFAULT_CONFIG_FILE);
if (config_ctx == NULL) {
ret = ENOMEM;
goto done;
}
switch (type) {
case COMPONENT_MONITOR:
error = sbus_error_new(dbus_req, DBUS_ERROR_NOT_SUPPORTED, NULL);
goto done;
break;
case COMPONENT_RESPONDER:
ret = sss_config_service_enable(config_ctx, name);
break;
case COMPONENT_BACKEND:
ret = sss_config_domain_enable(config_ctx, name);
break;
}
if (ret != EOK) {
goto done;
}
ret = sss_config_save(config_ctx);
if (ret != EOK) {
goto done;
}
done:
sss_config_close(&config_ctx);
if (ret == ENOMEM) {
return sbus_request_fail_and_finish(dbus_req, NULL);
} else if (error != NULL) {
return sbus_request_fail_and_finish(dbus_req, error);
} else if (ret != EOK) {
error = sbus_error_new(dbus_req, DBUS_ERROR_FAILED, "%s", strerror(ret));
return sbus_request_fail_and_finish(dbus_req, error);
}
return iface_ifp_components_Enable_finish(dbus_req);
#endif
}
int ifp_component_disable(struct sbus_request *dbus_req, void *data)
{
#ifndef HAVE_CONFIG_LIB
return sbus_request_fail_and_finish(dbus_req,
sbus_error_new(dbus_req, DBUS_ERROR_NOT_SUPPORTED, NULL));
#else
struct ifp_ctx *ctx = NULL;
DBusError *error = NULL;
const char *path = dbus_message_get_path(dbus_req->message);
char *name = NULL;
enum component_type type;
struct sss_config_ctx *config_ctx = NULL;
errno_t ret;
ctx = talloc_get_type(data, struct ifp_ctx);
if (ctx == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Invalid ifp context!\n");
ret = EINVAL;
goto done;
}
ret = check_and_get_component_from_path(dbus_req, ctx->rctx->cdb,
path, &type, &name);
if (ret != EOK) {
goto done;
}
config_ctx = sss_config_open(dbus_req, NULL, CONFDB_DEFAULT_CONFIG_FILE);
if (config_ctx == NULL) {
ret = ENOMEM;
goto done;
}
switch (type) {
case COMPONENT_MONITOR:
error = sbus_error_new(dbus_req, DBUS_ERROR_NOT_SUPPORTED, NULL);
goto done;
break;
case COMPONENT_RESPONDER:
ret = sss_config_service_disable(config_ctx, name);
break;
case COMPONENT_BACKEND:
ret = sss_config_domain_disable(config_ctx, name);
break;
}
if (ret != EOK) {
goto done;
}
ret = sss_config_save(config_ctx);
if (ret != EOK) {
goto done;
}
done:
sss_config_close(&config_ctx);
if (ret == ENOMEM) {
return sbus_request_fail_and_finish(dbus_req, NULL);
} else if (error != NULL) {
return sbus_request_fail_and_finish(dbus_req, error);
} else if (ret != EOK) {
error = sbus_error_new(dbus_req, DBUS_ERROR_FAILED, "%s", strerror(ret));
return sbus_request_fail_and_finish(dbus_req, error);
}
return iface_ifp_components_Disable_finish(dbus_req);
#endif
}
int ifp_component_change_debug_level(struct sbus_request *dbus_req,
void *data,
uint32_t arg_new_level)
{
#ifndef HAVE_CONFIG_LIB
return sbus_request_fail_and_finish(dbus_req,
sbus_error_new(dbus_req, DBUS_ERROR_NOT_SUPPORTED, NULL));
#else
struct ifp_ctx *ctx = NULL;
DBusError *error = NULL;
const char *path = dbus_message_get_path(dbus_req->message);
char *name = NULL;
enum component_type type;
struct sss_config_ctx *config_ctx = NULL;
const char *section = NULL;
errno_t ret;
ctx = talloc_get_type(data, struct ifp_ctx);
if (ctx == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Invalid ifp context!\n");
ret = EINVAL;
goto done;
}
ret = check_and_get_component_from_path(dbus_req, ctx->rctx->cdb,
path, &type, &name);
if (ret != EOK) {
goto done;
}
switch (type) {
case COMPONENT_MONITOR:
section = "sssd";
break;
case COMPONENT_RESPONDER:
section = name;
break;
case COMPONENT_BACKEND:
section = talloc_asprintf(dbus_req, "domain/%s", name);
break;
}
if (section == NULL) {
ret = ENOMEM;
goto done;
}
config_ctx = sss_config_open(dbus_req, NULL, CONFDB_DEFAULT_CONFIG_FILE);
if (config_ctx == NULL) {
ret = ENOMEM;
goto done;
}
ret = sss_config_set_debug_level(config_ctx, section, arg_new_level);
if (ret != EOK) {
goto done;
}
ret = sss_config_save(config_ctx);
if (ret != EOK) {
goto done;
}
ret = change_debug_level_tmp(ctx->rctx->cdb, name, type, arg_new_level);
if (ret != EOK) {
goto done;
}
done:
sss_config_close(&config_ctx);
if (ret == ENOMEM) {
return sbus_request_fail_and_finish(dbus_req, NULL);
} else if (ret != EOK) {
error = sbus_error_new(dbus_req, DBUS_ERROR_FAILED, "%s", strerror(ret));
return sbus_request_fail_and_finish(dbus_req, error);
}
return iface_ifp_components_ChangeDebugLevel_finish(dbus_req);
#endif
}
int ifp_component_change_debug_level_tmp(struct sbus_request *dbus_req,
void *data,
uint32_t arg_new_level)
{
struct ifp_ctx *ctx = NULL;
DBusError *error = NULL;
char *name = NULL;
enum component_type type;
errno_t ret;
ctx = talloc_get_type(data, struct ifp_ctx);
if (ctx == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Invalid ifp context!\n");
ret = EINVAL;
goto done;
}
ret = check_and_get_component_from_path(dbus_req, ctx->rctx->cdb,
dbus_req->path, &type, &name);
if (ret != EOK) {
goto done;
}
ret = change_debug_level_tmp(ctx->rctx->cdb, name, type, arg_new_level);
if (ret != EOK) {
goto done;
}
/* Touch configuration file to make sure debug level is reloaded. */
if (utime(CONFDB_DEFAULT_CONFIG_FILE, NULL) == -1) {
ret = errno;
goto done;
}
ret = EOK;
done:
if (ret != EOK) {
error = sbus_error_new(dbus_req, DBUS_ERROR_FAILED, "%s", strerror(ret));
return sbus_request_fail_and_finish(dbus_req, error);
}
return iface_ifp_components_ChangeDebugLevelTemporarily_finish(dbus_req);
}
void ifp_component_get_name(struct sbus_request *dbus_req,
void *data,
const char **_out)
{
struct ifp_ctx *ctx = NULL;
char *name = NULL;
errno_t ret;
*_out = NULL;
ctx = talloc_get_type(data, struct ifp_ctx);
if (ctx == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Invalid ifp context!\n");
return;
}
ret = check_and_get_component_from_path(dbus_req, ctx->rctx->cdb,
dbus_req->path, NULL, &name);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "Unknown object [%d]: %s\n",
ret, strerror(ret));
return;
}
*_out = name;
}
void ifp_component_get_debug_level(struct sbus_request *dbus_req,
void *data,
uint32_t *_out)
{
struct ifp_ctx *ctx = NULL;
const char *confdb_path = NULL;
char *name = NULL;
enum component_type type;
int level;
errno_t ret;
*_out = 0;
ctx = talloc_get_type(data, struct ifp_ctx);
if (ctx == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Invalid ifp context!\n");
return;
}
ret = check_and_get_component_from_path(dbus_req, ctx->rctx->cdb,
dbus_req->path, &type, &name);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "Unknown object [%d]: %s\n",
ret, strerror(ret));
return;
}
switch (type) {
case COMPONENT_MONITOR:
confdb_path = CONFDB_MONITOR_CONF_ENTRY;
break;
case COMPONENT_RESPONDER:
confdb_path = talloc_asprintf(dbus_req, CONFDB_SERVICE_PATH_TMPL, name);
break;
case COMPONENT_BACKEND:
confdb_path = talloc_asprintf(dbus_req, CONFDB_DOMAIN_PATH_TMPL, name);
break;
}
if (confdb_path == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory\n");
return;
}
ret = confdb_get_int(ctx->rctx->cdb, confdb_path,
CONFDB_SERVICE_DEBUG_LEVEL, SSSDBG_DEFAULT, &level);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "Unable to retrieve configuration option"
"[%d]: %s\n", ret, strerror(ret));
return;
}
*_out = level;
}
void ifp_component_get_enabled(struct sbus_request *dbus_req,
void *data,
bool *_out)
{
struct ifp_ctx *ctx = NULL;
const char *param = NULL;
char **values = NULL;
char *name = NULL;
enum component_type type;
errno_t ret;
int i;
*_out = false;
ctx = talloc_get_type(data, struct ifp_ctx);
if (ctx == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Invalid ifp context!\n");
return;
}
ret = check_and_get_component_from_path(dbus_req, ctx->rctx->cdb,
dbus_req->path, &type, &name);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "Unknown object [%d]: %s\n",
ret, strerror(ret));
return;
}
switch (type) {
case COMPONENT_MONITOR:
*_out = true;
return;
case COMPONENT_RESPONDER:
param = CONFDB_MONITOR_ACTIVE_SERVICES;
break;
case COMPONENT_BACKEND:
param = CONFDB_MONITOR_ACTIVE_DOMAINS;
break;
}
ret = confdb_get_string_as_list(ctx->rctx->cdb, dbus_req,
CONFDB_MONITOR_CONF_ENTRY, param, &values);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "Unable to retrieve configuration option"
"[%d]: %s\n", ret, strerror(ret));
return;
}
for (i = 0; values[i] != NULL; i++) {
if (strcmp(values[i], name) == 0) {
*_out = true;
return;
}
}
}
void ifp_component_get_type(struct sbus_request *dbus_req,
void *data,
const char **_out)
{
struct ifp_ctx *ctx = NULL;
enum component_type type;
errno_t ret;
*_out = NULL;
ctx = talloc_get_type(data, struct ifp_ctx);
if (ctx == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Invalid ifp context!\n");
return;
}
ret = check_and_get_component_from_path(dbus_req, ctx->rctx->cdb,
dbus_req->path, &type, NULL);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "Unknown object [%d]: %s\n",
ret, strerror(ret));
return;
}
switch (type) {
case COMPONENT_MONITOR:
*_out = "monitor";
break;
case COMPONENT_RESPONDER:
*_out = "responder";
break;
case COMPONENT_BACKEND:
*_out = "backend";
break;
}
}
void ifp_backend_get_providers(struct sbus_request *dbus_req,
void *data,
const char ***_out,
int *_out_len)
{
TALLOC_CTX *tmp_ctx = NULL;
struct ifp_ctx *ctx = NULL;
const char *confdb_path = NULL;
char *name = NULL;
enum component_type type;
const char **out = NULL;
char *value = NULL;
static const char *providers[] = {CONFDB_DOMAIN_ID_PROVIDER,
CONFDB_DOMAIN_AUTH_PROVIDER,
CONFDB_DOMAIN_ACCESS_PROVIDER,
CONFDB_DOMAIN_CHPASS_PROVIDER,
CONFDB_DOMAIN_SUDO_PROVIDER,
CONFDB_DOMAIN_AUTOFS_PROVIDER,
CONFDB_DOMAIN_SELINUX_PROVIDER,
CONFDB_DOMAIN_HOSTID_PROVIDER,
CONFDB_DOMAIN_SUBDOMAINS_PROVIDER};
int num_providers = sizeof(providers) / sizeof(providers[0]);
errno_t ret;
int i;
int j;
*_out = NULL;
*_out_len = 0;
tmp_ctx = talloc_new(NULL);
if (tmp_ctx == NULL) {
return;
}
ctx = talloc_get_type(data, struct ifp_ctx);
if (ctx == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Invalid ifp context!\n");
return;
}
ret = check_and_get_component_from_path(tmp_ctx, ctx->rctx->cdb,
dbus_req->path, &type, &name);
if (ret != EOK) {
DEBUG(SSSDBG_OP_FAILURE, "Unknown object [%d]: %s\n",
ret, strerror(ret));
return;
}
if (type != COMPONENT_BACKEND) {
return;
}
confdb_path = talloc_asprintf(tmp_ctx, CONFDB_DOMAIN_PATH_TMPL, name);
if (confdb_path == NULL) {
return;
}
out = talloc_zero_array(tmp_ctx, const char*, num_providers);
if (out == NULL) {
return;
}
j = 0;
for (i = 0; i < num_providers; i++) {
ret = confdb_get_string(ctx->rctx->cdb, tmp_ctx, confdb_path,
providers[i], NULL, &value);
if (ret != EOK) {
return;
}
if (value == NULL) {
continue;
}
out[j] = talloc_asprintf(out, "%s=%s", providers[i], value);
if (out[j] == NULL) {
return;
}
j++;
}
*_out = talloc_steal(dbus_req, out);
*_out_len = j;
talloc_free(tmp_ctx);
return;
}