summaryrefslogtreecommitdiffstats
path: root/src/responder/ifp/ifp_domains.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 05:31:45 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 05:31:45 +0000
commit74aa0bc6779af38018a03fd2cf4419fe85917904 (patch)
tree9cb0681aac9a94a49c153d5823e7a55d1513d91f /src/responder/ifp/ifp_domains.c
parentInitial commit. (diff)
downloadsssd-74aa0bc6779af38018a03fd2cf4419fe85917904.tar.xz
sssd-74aa0bc6779af38018a03fd2cf4419fe85917904.zip
Adding upstream version 2.9.4.upstream/2.9.4
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/responder/ifp/ifp_domains.c')
-rw-r--r--src/responder/ifp/ifp_domains.c1022
1 files changed, 1022 insertions, 0 deletions
diff --git a/src/responder/ifp/ifp_domains.c b/src/responder/ifp/ifp_domains.c
new file mode 100644
index 0000000..16d80e6
--- /dev/null
+++ b/src/responder/ifp/ifp_domains.c
@@ -0,0 +1,1022 @@
+/*
+ Authors:
+ Jakub Hrozek <jhrozek@redhat.com>
+ 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 <talloc.h>
+#include <tevent.h>
+#include <string.h>
+
+#include "db/sysdb.h"
+#include "util/util.h"
+#include "confdb/confdb.h"
+#include "responder/common/responder.h"
+#include "responder/ifp/ifp_domains.h"
+#include "responder/ifp/ifp_iface/ifp_iface_async.h"
+#include "sss_iface/sss_iface_async.h"
+
+#define RETURN_DOM_PROP(dbus_req, ctx, out, property) ({ \
+ struct sss_domain_info *__dom; \
+ errno_t __ret; \
+ \
+ __dom = get_domain_info_from_req((dbus_req), (ctx)); \
+ if (__dom == NULL) { \
+ __ret = ERR_DOMAIN_NOT_FOUND; \
+ } else { \
+ *(out) = __dom->property; \
+ __ret = EOK; \
+ } \
+ __ret; \
+})
+
+
+struct ifp_list_domains_state {
+ struct ifp_ctx *ifp_ctx;
+ const char **paths;
+};
+
+static void ifp_list_domains_done(struct tevent_req *subreq);
+
+struct tevent_req *
+ifp_list_domains_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sbus_request *sbus_req,
+ struct ifp_ctx *ifp_ctx)
+{
+ struct ifp_list_domains_state *state;
+ struct tevent_req *subreq;
+ struct tevent_req *req;
+ errno_t ret;
+
+ req = tevent_req_create(mem_ctx, &state, struct ifp_list_domains_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n");
+ return NULL;
+ }
+
+ state->ifp_ctx = ifp_ctx;
+
+ subreq = sss_dp_get_domains_send(state, ifp_ctx->rctx, false, NULL);
+ if (subreq == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create subrequest!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ tevent_req_set_callback(subreq, ifp_list_domains_done, req);
+
+ ret = EAGAIN;
+
+done:
+ if (ret != EAGAIN) {
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ }
+
+ return req;
+}
+
+static void ifp_list_domains_done(struct tevent_req *subreq)
+{
+ struct ifp_list_domains_state *state;
+ struct sss_domain_info *dom;
+ struct tevent_req *req;
+ size_t num_domains;
+ size_t pi;
+ errno_t ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct ifp_list_domains_state);
+
+ ret = sss_dp_get_domains_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to refresh domain objects\n");
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ ret = sysdb_master_domain_update(state->ifp_ctx->rctx->domains);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to refresh subdomain list\n");
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ num_domains = 0;
+ for (dom = state->ifp_ctx->rctx->domains;
+ dom != NULL;
+ dom = get_next_domain(dom, SSS_GND_DESCEND)) {
+ num_domains++;
+ }
+
+ state->paths = talloc_zero_array(state, const char *, num_domains + 1);
+ if (state->paths == NULL) {
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+
+ pi = 0;
+ for (dom = state->ifp_ctx->rctx->domains;
+ dom != NULL;
+ dom = get_next_domain(dom, SSS_GND_DESCEND)) {
+ state->paths[pi] = sbus_opath_compose(state->paths, IFP_PATH_DOMAINS, dom->name);
+ if (state->paths[pi] == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Could not create path for dom %s\n",
+ dom->name);
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ pi++;
+ }
+
+ tevent_req_done(req);
+ return;
+}
+
+errno_t ifp_list_domains_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ const char ***_paths)
+{
+ struct ifp_list_domains_state *state;
+ state = tevent_req_data(req, struct ifp_list_domains_state);
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ *_paths = talloc_steal(mem_ctx, state->paths);
+
+ return EOK;
+}
+
+struct ifp_find_domain_by_name_state {
+ struct ifp_ctx *ifp_ctx;
+ const char *name;
+ const char *path;
+};
+
+static void ifp_find_domain_by_name_done(struct tevent_req *subreq);
+
+struct tevent_req *
+ifp_find_domain_by_name_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sbus_request *sbus_req,
+ struct ifp_ctx *ifp_ctx,
+ const char *name)
+{
+ struct ifp_find_domain_by_name_state *state;
+ struct tevent_req *subreq;
+ struct tevent_req *req;
+ errno_t ret;
+
+ req = tevent_req_create(mem_ctx, &state, struct ifp_find_domain_by_name_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n");
+ return NULL;
+ }
+
+ state->ifp_ctx = ifp_ctx;
+ state->name = name;
+
+ subreq = sss_dp_get_domains_send(state, ifp_ctx->rctx, false, NULL);
+ if (subreq == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create subrequest!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ tevent_req_set_callback(subreq, ifp_find_domain_by_name_done, req);
+
+ ret = EAGAIN;
+
+done:
+ if (ret != EAGAIN) {
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ }
+
+ return req;
+}
+
+static void ifp_find_domain_by_name_done(struct tevent_req *subreq)
+{
+ struct ifp_find_domain_by_name_state *state;
+ struct sss_domain_info *iter;
+ struct tevent_req *req;
+ errno_t ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct ifp_find_domain_by_name_state);
+
+ ret = sss_dp_get_domains_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to refresh domain objects\n");
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ ret = sysdb_master_domain_update(state->ifp_ctx->rctx->domains);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Failed to refresh subdomain list\n");
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ /* Reply with the domain that was asked for */
+ for (iter = state->ifp_ctx->rctx->domains;
+ iter != NULL;
+ iter = get_next_domain(iter, SSS_GND_DESCEND)) {
+ if (strcasecmp(iter->name, state->name) == 0) {
+ break;
+ }
+ }
+
+ if (iter == NULL) {
+ DEBUG(SSSDBG_MINOR_FAILURE, "Domain not found: %s\n", state->name);
+ tevent_req_error(req, ERR_DOMAIN_NOT_FOUND);
+ return;
+ }
+
+ state->path = sbus_opath_compose(state, IFP_PATH_DOMAINS, iter->name);
+ if (state->path == NULL) {
+ DEBUG(SSSDBG_MINOR_FAILURE,
+ "Could not create path for domain %s, skipping\n", iter->name);
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+
+ tevent_req_done(req);
+ return;
+}
+
+errno_t
+ifp_find_domain_by_name_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ const char **_path)
+{
+ struct ifp_find_domain_by_name_state *state;
+ state = tevent_req_data(req, struct ifp_find_domain_by_name_state);
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ *_path = talloc_steal(mem_ctx, state->path);
+
+ return EOK;
+}
+
+static struct sss_domain_info *
+get_domain_info_from_req(struct sbus_request *dbus_req,
+ struct ifp_ctx *ctx)
+{
+ struct sss_domain_info *domains = NULL;
+ struct sss_domain_info *iter = NULL;
+ char *name = NULL;
+
+ name = sbus_opath_object_name(NULL, dbus_req->path, IFP_PATH_DOMAINS);
+ if (name == NULL) {
+ return NULL;
+ }
+
+ DEBUG(SSSDBG_TRACE_INTERNAL, "Looking for domain %s\n", name);
+
+ domains = ctx->rctx->domains;
+ for (iter = domains; iter != NULL;
+ iter = get_next_domain(iter, SSS_GND_DESCEND)) {
+ if (strcasecmp(iter->name, name) == 0) {
+ break;
+ }
+ }
+
+ talloc_free(name);
+ return iter;
+}
+
+static errno_t
+get_server_list(TALLOC_CTX *mem_ctx,
+ struct sbus_request *dbus_req,
+ struct ifp_ctx *ctx,
+ const char ***_out,
+ bool backup)
+{
+ TALLOC_CTX *tmp_ctx;
+ static const char *srv[] = {"_srv_", NULL};
+ struct sss_domain_info *dom = NULL;
+ char *conf_path = NULL;
+ const char *option = NULL;
+ const char **out = NULL;
+ char **servers = NULL;
+ int num_servers;
+ errno_t ret;
+ int i;
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ DEBUG(SSSDBG_FATAL_FAILURE, "Out of memory!\n");
+ return ENOMEM;
+ }
+
+ dom = get_domain_info_from_req(dbus_req, ctx);
+ if (dom == NULL) {
+ return ERR_DOMAIN_NOT_FOUND;
+ }
+
+ if (dom->parent != NULL) {
+ /* subdomains are not present in configuration */
+ ret = ENOENT;
+ goto done;
+ }
+
+ conf_path = talloc_asprintf(tmp_ctx, CONFDB_DOMAIN_PATH_TMPL, dom->name);
+ if (conf_path == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ /* TODO: replace hardcoded values with option names from the provider */
+ if (strcasecmp(dom->provider, "ldap") == 0) {
+ option = backup == false ? "ldap_uri" : "ldap_backup_uri";
+ } else if (strcasecmp(dom->provider, "ipa") == 0) {
+ option = backup == false ? "ipa_server" : "ipa_backup_server";
+ } else if (strcasecmp(dom->provider, "ad") == 0) {
+ option = backup == false ? "ad_server" : "ad_backup_server";
+ } else {
+ ret = EINVAL;
+ goto done;
+ }
+
+ ret = confdb_get_string_as_list(ctx->rctx->cdb, tmp_ctx, conf_path,
+ option, &servers);
+ if (ret != EOK) {
+ goto done;
+ }
+
+ for (num_servers = 0; servers[num_servers] != NULL; num_servers++);
+
+ if (num_servers == 0) {
+ ret = ENOENT;
+ goto done;
+ }
+
+ out = talloc_zero_array(mem_ctx, const char *, num_servers + 1);
+ if (out == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ for (i = 0; i < num_servers; i++) {
+ out[i] = talloc_steal(out, servers[i]);
+ }
+
+ *_out = out;
+
+ ret = EOK;
+
+done:
+ talloc_free(tmp_ctx);
+
+ if (ret == ENOENT) {
+ *_out = srv;
+ }
+
+ return ret;
+}
+
+errno_t
+ifp_dom_get_name(TALLOC_CTX *mem_ctx,
+ struct sbus_request *sbus_req,
+ struct ifp_ctx *ctx,
+ const char **_out)
+{
+ return RETURN_DOM_PROP(sbus_req, ctx, _out, name);
+}
+
+errno_t
+ifp_dom_get_provider(TALLOC_CTX *mem_ctx,
+ struct sbus_request *sbus_req,
+ struct ifp_ctx *ctx,
+ const char **_out)
+{
+ return RETURN_DOM_PROP(sbus_req, ctx, _out, provider);
+}
+
+errno_t
+ifp_dom_get_primary_servers(TALLOC_CTX *mem_ctx,
+ struct sbus_request *sbus_req,
+ struct ifp_ctx *ctx,
+ const char ***_out)
+{
+ return get_server_list(mem_ctx, sbus_req, ctx, _out, false);
+}
+
+errno_t
+ifp_dom_get_backup_servers(TALLOC_CTX *mem_ctx,
+ struct sbus_request *sbus_req,
+ struct ifp_ctx *ctx,
+ const char ***_out)
+{
+ return get_server_list(mem_ctx, sbus_req, ctx, _out, true);
+}
+
+errno_t
+ifp_dom_get_min_id(TALLOC_CTX *mem_ctx,
+ struct sbus_request *sbus_req,
+ struct ifp_ctx *ctx,
+ uint32_t *_out)
+{
+ return RETURN_DOM_PROP(sbus_req, ctx, _out, id_min);
+}
+
+errno_t
+ifp_dom_get_max_id(TALLOC_CTX *mem_ctx,
+ struct sbus_request *sbus_req,
+ struct ifp_ctx *ctx,
+ uint32_t *_out)
+{
+ return RETURN_DOM_PROP(sbus_req, ctx, _out, id_max);
+}
+
+errno_t
+ifp_dom_get_realm(TALLOC_CTX *mem_ctx,
+ struct sbus_request *sbus_req,
+ struct ifp_ctx *ctx,
+ const char **_out)
+{
+ return RETURN_DOM_PROP(sbus_req, ctx, _out, realm);
+}
+
+errno_t
+ifp_dom_get_forest(TALLOC_CTX *mem_ctx,
+ struct sbus_request *sbus_req,
+ struct ifp_ctx *ctx,
+ const char **_out)
+{
+ return RETURN_DOM_PROP(sbus_req, ctx, _out, forest);
+}
+
+errno_t
+ifp_dom_get_login_format(TALLOC_CTX *mem_ctx,
+ struct sbus_request *sbus_req,
+ struct ifp_ctx *ctx,
+ const char **_out)
+{
+ return RETURN_DOM_PROP(sbus_req, ctx, _out, names->re_pattern);
+}
+
+errno_t
+ifp_dom_get_fqdn_format(TALLOC_CTX *mem_ctx,
+ struct sbus_request *sbus_req,
+ struct ifp_ctx *ctx,
+ const char **_out)
+{
+ return RETURN_DOM_PROP(sbus_req, ctx, _out, names->fq_fmt);
+}
+
+errno_t
+ifp_dom_get_enumerable(TALLOC_CTX *mem_ctx,
+ struct sbus_request *sbus_req,
+ struct ifp_ctx *ctx,
+ bool *_out)
+{
+ return RETURN_DOM_PROP(sbus_req, ctx, _out, enumerate);
+}
+
+errno_t
+ifp_dom_get_use_fqdn(TALLOC_CTX *mem_ctx,
+ struct sbus_request *sbus_req,
+ struct ifp_ctx *ctx,
+ bool *_out)
+{
+ return RETURN_DOM_PROP(sbus_req, ctx, _out, fqnames);
+}
+
+errno_t
+ifp_dom_get_subdomain(TALLOC_CTX *mem_ctx,
+ struct sbus_request *sbus_req,
+ struct ifp_ctx *ctx,
+ bool *_out)
+{
+ struct sss_domain_info *dom;
+
+ dom = get_domain_info_from_req(sbus_req, ctx);
+ if (dom == NULL) {
+ return ERR_DOMAIN_NOT_FOUND;
+ }
+
+ *_out = dom->parent != NULL ? true : false;
+
+ return EOK;
+}
+
+errno_t
+ifp_dom_get_parent_domain(TALLOC_CTX *mem_ctx,
+ struct sbus_request *sbus_req,
+ struct ifp_ctx *ctx,
+ const char **_out)
+{
+ struct sss_domain_info *dom;
+ const char *path;
+
+ dom = get_domain_info_from_req(sbus_req, ctx);
+ if (dom == NULL) {
+ return ERR_DOMAIN_NOT_FOUND;
+ }
+
+ if (dom->parent == NULL) {
+ *_out = "/";
+ return EOK;
+ }
+
+ path = sbus_opath_compose(mem_ctx, IFP_PATH_DOMAINS, dom->parent->name);
+ if (path == NULL) {
+ return ENOMEM;
+ }
+
+ *_out = path;
+
+ return EOK;
+}
+
+struct ifp_domains_domain_is_online_state {
+ bool is_online;
+};
+
+static void ifp_domains_domain_is_online_done(struct tevent_req *subreq);
+
+struct tevent_req *
+ifp_domains_domain_is_online_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sbus_request *sbus_req,
+ struct ifp_ctx *ifp_ctx)
+{
+ struct ifp_domains_domain_is_online_state *state;
+ struct sss_domain_info *dom;
+ struct tevent_req *subreq;
+ struct tevent_req *req;
+ struct be_conn *be_conn;
+ errno_t ret;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct ifp_domains_domain_is_online_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n");
+ return NULL;
+ }
+
+ dom = get_domain_info_from_req(sbus_req, ifp_ctx);
+ if (dom == NULL) {
+ ret = ERR_DOMAIN_NOT_FOUND;
+ goto done;
+ }
+
+ ret = sss_dp_get_domain_conn(ifp_ctx->rctx, dom->conn_name, &be_conn);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "BUG: The Data Provider connection for "
+ "%s is not available!\n", dom->name);
+ goto done;
+ }
+
+ subreq = sbus_call_dp_backend_IsOnline_send(state, be_conn->conn,
+ be_conn->bus_name, SSS_BUS_PATH, dom->name);
+ if (subreq == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create subrequest!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ tevent_req_set_callback(subreq, ifp_domains_domain_is_online_done, req);
+
+ ret = EAGAIN;
+
+done:
+ if (ret != EAGAIN) {
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ }
+
+ return req;
+}
+
+static void ifp_domains_domain_is_online_done(struct tevent_req *subreq)
+{
+ struct ifp_domains_domain_is_online_state *state;
+ struct tevent_req *req;
+ errno_t ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct ifp_domains_domain_is_online_state);
+
+ ret = sbus_call_dp_backend_IsOnline_recv(subreq, &state->is_online);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ tevent_req_done(req);
+ return;
+}
+
+errno_t
+ifp_domains_domain_is_online_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ bool *_is_online)
+{
+ struct ifp_domains_domain_is_online_state *state;
+ state = tevent_req_data(req, struct ifp_domains_domain_is_online_state);
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ *_is_online = state->is_online;
+
+ return EOK;
+}
+
+struct ifp_domains_domain_list_services_state {
+ const char **services;
+};
+
+static void ifp_domains_domain_list_services_done(struct tevent_req *subreq);
+
+struct tevent_req *
+ifp_domains_domain_list_services_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sbus_request *sbus_req,
+ struct ifp_ctx *ifp_ctx)
+{
+ struct ifp_domains_domain_list_services_state *state;
+ struct sss_domain_info *dom;
+ struct tevent_req *subreq;
+ struct tevent_req *req;
+ struct be_conn *be_conn;
+ errno_t ret;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct ifp_domains_domain_list_services_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n");
+ return NULL;
+ }
+
+ dom = get_domain_info_from_req(sbus_req, ifp_ctx);
+ if (dom == NULL) {
+ ret = ERR_DOMAIN_NOT_FOUND;
+ goto done;
+ }
+
+ ret = sss_dp_get_domain_conn(ifp_ctx->rctx, dom->conn_name, &be_conn);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "BUG: The Data Provider connection for "
+ "%s is not available!\n", dom->name);
+ goto done;
+ }
+
+ subreq = sbus_call_dp_failover_ListServices_send(state, be_conn->conn,
+ be_conn->bus_name, SSS_BUS_PATH, dom->name);
+ if (subreq == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create subrequest!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ tevent_req_set_callback(subreq, ifp_domains_domain_list_services_done, req);
+
+ ret = EAGAIN;
+
+done:
+ if (ret != EAGAIN) {
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ }
+
+ return req;
+}
+
+static void ifp_domains_domain_list_services_done(struct tevent_req *subreq)
+{
+ struct ifp_domains_domain_list_services_state *state;
+ struct tevent_req *req;
+ errno_t ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct ifp_domains_domain_list_services_state);
+
+ ret = sbus_call_dp_failover_ListServices_recv(state, subreq, &state->services);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ tevent_req_done(req);
+ return;
+}
+
+errno_t
+ifp_domains_domain_list_services_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ const char ***_services)
+{
+ struct ifp_domains_domain_list_services_state *state;
+ state = tevent_req_data(req, struct ifp_domains_domain_list_services_state);
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ *_services = talloc_steal(mem_ctx, state->services);
+
+ return EOK;
+}
+
+struct ifp_domains_domain_active_server_state {
+ const char *server;
+};
+
+static void ifp_domains_domain_active_server_done(struct tevent_req *subreq);
+
+struct tevent_req *
+ifp_domains_domain_active_server_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sbus_request *sbus_req,
+ struct ifp_ctx *ifp_ctx,
+ const char *service)
+{
+ struct ifp_domains_domain_active_server_state *state;
+ struct sss_domain_info *dom;
+ struct tevent_req *subreq;
+ struct tevent_req *req;
+ struct be_conn *be_conn;
+ errno_t ret;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct ifp_domains_domain_active_server_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n");
+ return NULL;
+ }
+
+ dom = get_domain_info_from_req(sbus_req, ifp_ctx);
+ if (dom == NULL) {
+ ret = ERR_DOMAIN_NOT_FOUND;
+ goto done;
+ }
+
+ ret = sss_dp_get_domain_conn(ifp_ctx->rctx, dom->conn_name, &be_conn);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "BUG: The Data Provider connection for "
+ "%s is not available!\n", dom->name);
+ goto done;
+ }
+
+ subreq = sbus_call_dp_failover_ActiveServer_send(state, be_conn->conn,
+ be_conn->bus_name, SSS_BUS_PATH, service);
+ if (subreq == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create subrequest!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ tevent_req_set_callback(subreq, ifp_domains_domain_active_server_done, req);
+
+ ret = EAGAIN;
+
+done:
+if (ret != EAGAIN) {
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+}
+
+ return req;
+}
+
+static void ifp_domains_domain_active_server_done(struct tevent_req *subreq)
+{
+ struct ifp_domains_domain_active_server_state *state;
+ struct tevent_req *req;
+ errno_t ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct ifp_domains_domain_active_server_state);
+
+ ret = sbus_call_dp_failover_ActiveServer_recv(state, subreq, &state->server);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ tevent_req_done(req);
+ return;
+}
+
+errno_t
+ifp_domains_domain_active_server_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ const char **_server)
+{
+ struct ifp_domains_domain_active_server_state *state;
+ state = tevent_req_data(req, struct ifp_domains_domain_active_server_state);
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ *_server = talloc_steal(mem_ctx, state->server);
+
+ return EOK;
+}
+
+struct ifp_domains_domain_list_servers_state {
+ const char **servers;
+};
+
+static void ifp_domains_domain_list_servers_done(struct tevent_req *subreq);
+
+struct tevent_req *
+ifp_domains_domain_list_servers_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sbus_request *sbus_req,
+ struct ifp_ctx *ifp_ctx,
+ const char *service)
+{
+ struct ifp_domains_domain_list_servers_state *state;
+ struct sss_domain_info *dom;
+ struct tevent_req *subreq;
+ struct tevent_req *req;
+ struct be_conn *be_conn;
+ errno_t ret;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct ifp_domains_domain_list_servers_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n");
+ return NULL;
+ }
+
+ dom = get_domain_info_from_req(sbus_req, ifp_ctx);
+ if (dom == NULL) {
+ ret = ERR_DOMAIN_NOT_FOUND;
+ goto done;
+ }
+
+ ret = sss_dp_get_domain_conn(ifp_ctx->rctx, dom->conn_name, &be_conn);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "BUG: The Data Provider connection for "
+ "%s is not available!\n", dom->name);
+ goto done;
+ }
+
+ subreq = sbus_call_dp_failover_ListServers_send(state, be_conn->conn,
+ be_conn->bus_name, SSS_BUS_PATH, service);
+ if (subreq == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create subrequest!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ tevent_req_set_callback(subreq, ifp_domains_domain_list_servers_done, req);
+
+ ret = EAGAIN;
+
+done:
+ if (ret != EAGAIN) {
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ }
+
+ return req;
+}
+
+static void ifp_domains_domain_list_servers_done(struct tevent_req *subreq)
+{
+ struct ifp_domains_domain_list_servers_state *state;
+ struct tevent_req *req;
+ errno_t ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+ state = tevent_req_data(req, struct ifp_domains_domain_list_servers_state);
+
+ ret = sbus_call_dp_failover_ListServers_recv(state, subreq, &state->servers);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ tevent_req_done(req);
+ return;
+}
+
+errno_t
+ifp_domains_domain_list_servers_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req,
+ const char ***_servers)
+{
+ struct ifp_domains_domain_list_servers_state *state;
+ state = tevent_req_data(req, struct ifp_domains_domain_list_servers_state);
+
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ *_servers = talloc_steal(mem_ctx, state->servers);
+
+ return EOK;
+}
+
+struct ifp_domains_domain_refresh_access_rules_state {
+ int dummy;
+};
+
+static void ifp_domains_domain_refresh_access_rules_done(struct tevent_req *subreq);
+
+struct tevent_req *
+ifp_domains_domain_refresh_access_rules_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sbus_request *sbus_req,
+ struct ifp_ctx *ifp_ctx)
+{
+ struct ifp_domains_domain_refresh_access_rules_state *state;
+ struct sss_domain_info *dom;
+ struct tevent_req *subreq;
+ struct tevent_req *req;
+ struct be_conn *be_conn;
+ errno_t ret;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct ifp_domains_domain_refresh_access_rules_state);
+ if (req == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create tevent request!\n");
+ return NULL;
+ }
+
+ dom = get_domain_info_from_req(sbus_req, ifp_ctx);
+ if (dom == NULL) {
+ ret = ERR_DOMAIN_NOT_FOUND;
+ goto done;
+ }
+
+ ret = sss_dp_get_domain_conn(ifp_ctx->rctx, dom->conn_name, &be_conn);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "BUG: The Data Provider connection for "
+ "%s is not available!\n", dom->name);
+ goto done;
+ }
+
+ subreq = sbus_call_dp_access_RefreshRules_send(state, be_conn->conn,
+ be_conn->bus_name, SSS_BUS_PATH);
+ if (subreq == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create subrequest!\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ tevent_req_set_callback(subreq, ifp_domains_domain_refresh_access_rules_done, req);
+
+ ret = EAGAIN;
+
+done:
+if (ret != EAGAIN) {
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+}
+
+ return req;
+}
+
+static void ifp_domains_domain_refresh_access_rules_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req;
+ errno_t ret;
+
+ req = tevent_req_callback_data(subreq, struct tevent_req);
+
+ ret = sbus_call_dp_access_RefreshRules_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ tevent_req_done(req);
+ return;
+}
+
+errno_t
+ifp_domains_domain_refresh_access_rules_recv(TALLOC_CTX *mem_ctx,
+ struct tevent_req *req)
+{
+ TEVENT_REQ_RETURN_ON_ERROR(req);
+
+ return EOK;
+}