From 590582be38cdbfde387fcc57df92903d48c5a083 Mon Sep 17 00:00:00 2001 From: Jakub Hrozek Date: Tue, 22 Apr 2014 15:38:08 +0200 Subject: IFP: Add ListDomains and FindDomainByName MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Pavel Březina --- Makefile.am | 2 + src/responder/ifp/ifp_domains.c | 234 ++++++++++++++++++++++++++++++++ src/responder/ifp/ifp_domains.h | 40 ++++++ src/responder/ifp/ifp_iface.xml | 9 ++ src/responder/ifp/ifp_iface_generated.c | 46 +++++++ src/responder/ifp/ifp_iface_generated.h | 10 ++ src/responder/ifp/ifpsrv.c | 3 + 7 files changed, 344 insertions(+) create mode 100644 src/responder/ifp/ifp_domains.c create mode 100644 src/responder/ifp/ifp_domains.h diff --git a/Makefile.am b/Makefile.am index 5f702e3fc..cf925bc51 100644 --- a/Makefile.am +++ b/Makefile.am @@ -485,6 +485,7 @@ dist_noinst_HEADERS = \ src/responder/autofs/autofs_private.h \ src/responder/ssh/sshsrv_private.h \ src/responder/ifp/ifp_private.h \ + src/responder/ifp/ifp_domains.h \ src/sbus/sbus_client.h \ src/sbus/sssd_dbus.h \ src/sbus/sssd_dbus_meta.h \ @@ -858,6 +859,7 @@ sssd_ifp_SOURCES = \ src/responder/ifp/ifp_iface_generated.c \ src/responder/ifp/ifp_iface_generated.h \ src/responder/ifp/ifpsrv_util.c \ + src/responder/ifp/ifp_domains.c \ $(SSSD_UTIL_OBJ) \ $(SSSD_RESPONDER_OBJ) sssd_ifp_CFLAGS = \ diff --git a/src/responder/ifp/ifp_domains.c b/src/responder/ifp/ifp_domains.c new file mode 100644 index 000000000..a06ba471c --- /dev/null +++ b/src/responder/ifp/ifp_domains.c @@ -0,0 +1,234 @@ +/* + Authors: + Jakub Hrozek + Pavel Březina + + 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 . +*/ + +#include + +#include "db/sysdb.h" +#include "util/util.h" +#include "confdb/confdb.h" +#include "responder/common/responder.h" +#include "responder/ifp/ifp_domains.h" + +static void ifp_list_domains_process(struct tevent_req *req); + +int ifp_list_domains(struct sbus_request *dbus_req, + void *data) +{ + struct ifp_ctx *ifp_ctx; + struct ifp_req *ireq; + struct tevent_req *req; + DBusError *error; + errno_t ret; + + ifp_ctx = talloc_get_type(data, struct ifp_ctx); + if (ifp_ctx == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Invalid ifp context!\n"); + error = sbus_error_new(dbus_req, DBUS_ERROR_FAILED, + "Invalid ifp context!"); + return sbus_request_fail_and_finish(dbus_req, error); + } + + ret = ifp_req_create(dbus_req, ifp_ctx, &ireq); + if (ret != EOK) { + error = sbus_error_new(dbus_req, DBUS_ERROR_FAILED, + "%s", sss_strerror(ret)); + return sbus_request_fail_and_finish(dbus_req, error); + } + + req = sss_dp_get_domains_send(ireq, ifp_ctx->rctx, false, NULL); + if (req == NULL) { + return sbus_request_finish(ireq->dbus_req, NULL); + } + + tevent_req_set_callback(req, ifp_list_domains_process, ireq); + + return EOK; +} + +static void ifp_list_domains_process(struct tevent_req *req) +{ + struct sss_domain_info *dom; + struct ifp_req *ireq; + const char **paths; + char *p; + DBusError *error; + size_t num_domains; + size_t pi; + errno_t ret; + + ireq = tevent_req_callback_data(req, struct ifp_req); + + ret = sss_dp_get_domains_recv(req); + talloc_free(req); + if (ret != EOK) { + error = sbus_error_new(ireq->dbus_req, DBUS_ERROR_FAILED, + "Failed to refresh domain objects\n"); + sbus_request_fail_and_finish(ireq->dbus_req, error); + return; + } + + ret = sysdb_master_domain_update(ireq->ifp_ctx->rctx->domains); + if (ret != EOK) { + error = sbus_error_new(ireq->dbus_req, DBUS_ERROR_FAILED, + "Failed to refresh subdomain list\n"); + sbus_request_fail_and_finish(ireq->dbus_req, error); + return; + } + + num_domains = 0; + for (dom = ireq->ifp_ctx->rctx->domains; + dom != NULL; + dom = get_next_domain(dom, true)) { + num_domains++; + } + + paths = talloc_zero_array(ireq, const char *, num_domains); + if (paths == NULL) { + sbus_request_finish(ireq->dbus_req, NULL); + return; + } + + pi = 0; + for (dom = ireq->ifp_ctx->rctx->domains; + dom != NULL; + dom = get_next_domain(dom, true)) { + p = ifp_reply_objpath(ireq, INFOPIPE_DOMAIN_PATH_PFX, dom->name); + if (p == NULL) { + DEBUG(SSSDBG_MINOR_FAILURE, + "Could not create path for dom %s, skipping\n", dom->name); + continue; + } + paths[pi] = p; + pi++; + } + + ret = infopipe_iface_ListDomains_finish(ireq->dbus_req, paths, num_domains); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "Could not finish request!\n"); + } +} + +struct ifp_get_domain_state { + const char *name; + struct ifp_req *ireq; +}; + +static void ifp_find_domain_by_name_process(struct tevent_req *req); + +int ifp_find_domain_by_name(struct sbus_request *dbus_req, + void *data, + const char *arg_name) +{ + struct ifp_ctx *ifp_ctx; + struct ifp_req *ireq; + struct tevent_req *req; + struct ifp_get_domain_state *state; + DBusError *error; + errno_t ret; + + ifp_ctx = talloc_get_type(data, struct ifp_ctx); + if (ifp_ctx == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n"); + error = sbus_error_new(dbus_req, DBUS_ERROR_FAILED, + "Invalid ifp context!"); + return sbus_request_fail_and_finish(dbus_req, error); + } + + ret = ifp_req_create(dbus_req, ifp_ctx, &ireq); + if (ret != EOK) { + error = sbus_error_new(dbus_req, DBUS_ERROR_FAILED, + "%s", sss_strerror(ret)); + return sbus_request_fail_and_finish(dbus_req, error); + } + + state = talloc_zero(ireq, struct ifp_get_domain_state); + if (state == NULL) { + return sbus_request_finish(dbus_req, NULL); + } + state->name = arg_name; + state->ireq = ireq; + + req = sss_dp_get_domains_send(ireq, ifp_ctx->rctx, false, NULL); + if (req == NULL) { + return sbus_request_finish(dbus_req, NULL); + } + tevent_req_set_callback(req, ifp_find_domain_by_name_process, state); + return EOK; +} + +static void ifp_find_domain_by_name_process(struct tevent_req *req) +{ + errno_t ret; + struct ifp_req *ireq; + struct ifp_get_domain_state *state; + struct sss_domain_info *iter; + const char *path; + DBusError *error; + + state = tevent_req_callback_data(req, struct ifp_get_domain_state); + ireq = state->ireq; + + ret = sss_dp_get_domains_recv(req); + talloc_free(req); + if (ret != EOK) { + error = sbus_error_new(ireq->dbus_req, DBUS_ERROR_FAILED, + "Failed to refresh domain objects\n"); + sbus_request_fail_and_finish(ireq->dbus_req, error); + return; + } + + ret = sysdb_master_domain_update(ireq->ifp_ctx->rctx->domains); + if (ret != EOK) { + error = sbus_error_new(ireq->dbus_req, DBUS_ERROR_FAILED, + "Failed to refresh subdomain list\n"); + sbus_request_fail_and_finish(ireq->dbus_req, error); + return; + } + + /* Reply with the domain that was asked for */ + for (iter = ireq->ifp_ctx->rctx->domains; + iter != NULL; + iter = get_next_domain(iter, true)) { + if (strcasecmp(iter->name, state->name) == 0) { + break; + } + } + + if (iter == NULL) { + error = sbus_error_new(ireq->dbus_req, DBUS_ERROR_FAILED, + "No such domain\n"); + sbus_request_fail_and_finish(ireq->dbus_req, error); + return; + } + + path = ifp_reply_objpath(ireq, INFOPIPE_DOMAIN_PATH_PFX, iter->name); + if (path == NULL) { + DEBUG(SSSDBG_MINOR_FAILURE, + "Could not create path for domain %s, skipping\n", iter->name); + sbus_request_finish(ireq->dbus_req, NULL); + return; + } + + ret = infopipe_iface_FindDomainByName_finish(ireq->dbus_req, path); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "Could not finish request!\n"); + } +} diff --git a/src/responder/ifp/ifp_domains.h b/src/responder/ifp/ifp_domains.h new file mode 100644 index 000000000..32771a93c --- /dev/null +++ b/src/responder/ifp/ifp_domains.h @@ -0,0 +1,40 @@ +/* + Authors: + Jakub Hrozek + Pavel Březina + + 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 . +*/ + +#ifndef IFP_DOMAINS_H_ +#define IFP_DOMAINS_H_ + +#include "responder/ifp/ifp_iface_generated.h" +#include "responder/ifp/ifp_private.h" + +#define INFOPIPE_DOMAIN_PATH_PFX "/org/freedesktop/sssd/infopipe/Domains" +#define INFOPIPE_DOMAIN_PATH INFOPIPE_DOMAIN_PATH_PFX"*" + +/* org.freedesktop.sssd.infopipe */ + +int ifp_list_domains(struct sbus_request *dbus_req, + void *data); + +int ifp_find_domain_by_name(struct sbus_request *dbus_req, + void *data, + const char *arg_name); + +#endif /* IFP_DOMAINS_H_ */ diff --git a/src/responder/ifp/ifp_iface.xml b/src/responder/ifp/ifp_iface.xml index 4893e2df5..af75ae88d 100644 --- a/src/responder/ifp/ifp_iface.xml +++ b/src/responder/ifp/ifp_iface.xml @@ -21,5 +21,14 @@ + + + + + + + + + diff --git a/src/responder/ifp/ifp_iface_generated.c b/src/responder/ifp/ifp_iface_generated.c index 91efda251..fe203e240 100644 --- a/src/responder/ifp/ifp_iface_generated.c +++ b/src/responder/ifp/ifp_iface_generated.c @@ -40,6 +40,38 @@ int infopipe_iface_GetUserGroups_finish(struct sbus_request *req, const char *ar DBUS_TYPE_INVALID); } +/* arguments for org.freedesktop.sssd.infopipe.FindDomainByName */ +const struct sbus_arg_meta infopipe_iface_FindDomainByName__in[] = { + { "name", "s" }, + { NULL, } +}; + +/* arguments for org.freedesktop.sssd.infopipe.FindDomainByName */ +const struct sbus_arg_meta infopipe_iface_FindDomainByName__out[] = { + { "domain", "o" }, + { NULL, } +}; + +int infopipe_iface_FindDomainByName_finish(struct sbus_request *req, const char *arg_domain) +{ + return sbus_request_return_and_finish(req, + DBUS_TYPE_OBJECT_PATH, &arg_domain, + DBUS_TYPE_INVALID); +} + +/* arguments for org.freedesktop.sssd.infopipe.ListDomains */ +const struct sbus_arg_meta infopipe_iface_ListDomains__out[] = { + { "domain", "ao" }, + { NULL, } +}; + +int infopipe_iface_ListDomains_finish(struct sbus_request *req, const char *arg_domain[], int len_domain) +{ + return sbus_request_return_and_finish(req, + DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, &arg_domain, len_domain, + DBUS_TYPE_INVALID); +} + /* methods for org.freedesktop.sssd.infopipe */ const struct sbus_method_meta infopipe_iface__methods[] = { { @@ -63,6 +95,20 @@ const struct sbus_method_meta infopipe_iface__methods[] = { offsetof(struct infopipe_iface, GetUserGroups), invoke_s_method, }, + { + "FindDomainByName", /* name */ + infopipe_iface_FindDomainByName__in, + infopipe_iface_FindDomainByName__out, + offsetof(struct infopipe_iface, FindDomainByName), + invoke_s_method, + }, + { + "ListDomains", /* name */ + NULL, /* no in_args */ + infopipe_iface_ListDomains__out, + offsetof(struct infopipe_iface, ListDomains), + NULL, /* no invoker */ + }, { NULL, } }; diff --git a/src/responder/ifp/ifp_iface_generated.h b/src/responder/ifp/ifp_iface_generated.h index 9b92b9b07..ca0e1c366 100644 --- a/src/responder/ifp/ifp_iface_generated.h +++ b/src/responder/ifp/ifp_iface_generated.h @@ -16,6 +16,8 @@ #define INFOPIPE_IFACE_PING "Ping" #define INFOPIPE_IFACE_GETUSERATTR "GetUserAttr" #define INFOPIPE_IFACE_GETUSERGROUPS "GetUserGroups" +#define INFOPIPE_IFACE_FINDDOMAINBYNAME "FindDomainByName" +#define INFOPIPE_IFACE_LISTDOMAINS "ListDomains" /* ------------------------------------------------------------------------ * DBus handlers @@ -41,11 +43,19 @@ struct infopipe_iface { sbus_msg_handler_fn Ping; sbus_msg_handler_fn GetUserAttr; int (*GetUserGroups)(struct sbus_request *req, void *data, const char *arg_user); + int (*FindDomainByName)(struct sbus_request *req, void *data, const char *arg_name); + int (*ListDomains)(struct sbus_request *req, void *data); }; /* finish function for GetUserGroups */ int infopipe_iface_GetUserGroups_finish(struct sbus_request *req, const char *arg_values[], int len_values); +/* finish function for FindDomainByName */ +int infopipe_iface_FindDomainByName_finish(struct sbus_request *req, const char *arg_domain); + +/* finish function for ListDomains */ +int infopipe_iface_ListDomains_finish(struct sbus_request *req, const char *arg_domain[], int len_domain); + /* ------------------------------------------------------------------------ * DBus Interface Metadata * diff --git a/src/responder/ifp/ifpsrv.c b/src/responder/ifp/ifpsrv.c index c6a50623a..2cffe6987 100644 --- a/src/responder/ifp/ifpsrv.c +++ b/src/responder/ifp/ifpsrv.c @@ -38,6 +38,7 @@ #include "monitor/monitor_interfaces.h" #include "confdb/confdb.h" #include "responder/ifp/ifp_private.h" +#include "responder/ifp/ifp_domains.h" #include "responder/common/responder_sbus.h" #define DEFAULT_ALLOWED_UIDS "0" @@ -68,6 +69,8 @@ struct infopipe_iface ifp_iface = { .Ping = ifp_ping, .GetUserAttr = ifp_user_get_attr, .GetUserGroups = ifp_user_get_groups, + .ListDomains = ifp_list_domains, + .FindDomainByName = ifp_find_domain_by_name, }; struct sysbus_iface { -- cgit