https://fedorahosted.org/sssd/ticket/2338
Depends on IFP: users and groups
From b08f37a1bf9593c74cdec8d829f0d125b9c66c30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrez...@redhat.com> Date: Mon, 18 May 2015 12:05:38 +0200 Subject: [PATCH 1/4] IFP: Implement org.freedesktop.sssd.infopipe.Cache[.Object] Resolves: https://fedorahosted.org/sssd/ticket/2338 --- Makefile.am | 2 + src/db/sysdb.c | 7 + src/db/sysdb.h | 1 + src/db/sysdb_private.h | 3 + src/db/sysdb_upgrade.c | 51 ++++ src/responder/ifp/ifp_cache.c | 305 +++++++++++++++++++++ src/responder/ifp/ifp_cache.h | 53 ++++ src/responder/ifp/ifp_groups.c | 52 ++++ src/responder/ifp/ifp_groups.h | 17 ++ src/responder/ifp/ifp_iface.c | 28 ++ src/responder/ifp/ifp_iface.xml | 23 ++ src/responder/ifp/ifp_iface_generated.c | 116 ++++++++ src/responder/ifp/ifp_iface_generated.h | 42 +++ src/responder/ifp/ifp_users.c | 52 ++++ src/responder/ifp/ifp_users.h | 17 ++ .../ifp/org.freedesktop.sssd.infopipe.conf | 2 + 16 files changed, 771 insertions(+) create mode 100644 src/responder/ifp/ifp_cache.c create mode 100644 src/responder/ifp/ifp_cache.h diff --git a/Makefile.am b/Makefile.am index 030cf7462186868ff8837b3ff15efb3cf8f7cfaf..de0cf9738ad399eb8ebce8968082a7dc1913d06a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -546,6 +546,7 @@ dist_noinst_HEADERS = \ src/responder/ifp/ifp_components.h \ src/responder/ifp/ifp_users.h \ src/responder/ifp/ifp_groups.h \ + src/responder/ifp/ifp_cache.h \ src/sbus/sbus_client.h \ src/sbus/sssd_dbus.h \ src/sbus/sssd_dbus_meta.h \ @@ -1090,6 +1091,7 @@ sssd_ifp_SOURCES = \ src/responder/ifp/ifp_components.c \ src/responder/ifp/ifp_users.c \ src/responder/ifp/ifp_groups.c \ + src/responder/ifp/ifp_cache.c \ $(SSSD_UTIL_OBJ) \ $(SSSD_RESPONDER_OBJ) sssd_ifp_CFLAGS = \ diff --git a/src/db/sysdb.c b/src/db/sysdb.c index 9da655759c0c35d52854b668693195b3360c5f8b..07a83a8a8e30df1b8e461a8d04866f2dbc53baf8 100644 --- a/src/db/sysdb.c +++ b/src/db/sysdb.c @@ -1265,6 +1265,13 @@ int sysdb_domain_init_internal(TALLOC_CTX *mem_ctx, } } + if (strcmp(version, SYSDB_VERSION_0_16) == 0) { + ret = sysdb_upgrade_16(sysdb, &version); + if (ret != EOK) { + goto done; + } + } + /* The version should now match SYSDB_VERSION. * If not, it means we didn't match any of the * known older versions. The DB might be diff --git a/src/db/sysdb.h b/src/db/sysdb.h index c3d2c1406321e01b325e04e0e3f263893eb91b2e..4035a39d3cd37390259cda79e6fcafe688bfd360 100644 --- a/src/db/sysdb.h +++ b/src/db/sysdb.h @@ -91,6 +91,7 @@ #define SYSDB_LAST_UPDATE "lastUpdate" #define SYSDB_CACHE_EXPIRE "dataExpireTimestamp" #define SYSDB_INITGR_EXPIRE "initgrExpireTimestamp" +#define SYSDB_CACHED "cached" #define SYSDB_AUTHORIZED_SERVICE "authorizedService" #define SYSDB_AUTHORIZED_HOST "authorizedHost" diff --git a/src/db/sysdb_private.h b/src/db/sysdb_private.h index 8a5b8be8cbcf0513fa4c471ac41f803a4e2a5b24..8e2c722b19d19212d95b3ff777cc414e18de41f1 100644 --- a/src/db/sysdb_private.h +++ b/src/db/sysdb_private.h @@ -23,6 +23,7 @@ #ifndef __INT_SYS_DB_H__ #define __INT_SYS_DB_H__ +#define SYSDB_VERSION_0_17 "0.17" #define SYSDB_VERSION_0_16 "0.16" #define SYSDB_VERSION_0_15 "0.15" #define SYSDB_VERSION_0_14 "0.14" @@ -68,6 +69,7 @@ "@IDXATTR: serviceProtocol\n" \ "@IDXATTR: sudoUser\n" \ "@IDXATTR: sshKnownHostsExpire\n" \ + "@IDXATTR: cached\n" \ "@IDXONE: 1\n" \ "\n" \ "dn: @MODULES\n" \ @@ -120,6 +122,7 @@ int sysdb_upgrade_12(struct sysdb_ctx *sysdb, const char **ver); int sysdb_upgrade_13(struct sysdb_ctx *sysdb, const char **ver); int sysdb_upgrade_14(struct sysdb_ctx *sysdb, const char **ver); int sysdb_upgrade_15(struct sysdb_ctx *sysdb, const char **ver); +int sysdb_upgrade_16(struct sysdb_ctx *sysdb, const char **ver); int add_string(struct ldb_message *msg, int flags, const char *attr, const char *value); diff --git a/src/db/sysdb_upgrade.c b/src/db/sysdb_upgrade.c index 6cebc877b86df7a8035bf95cfa51aa4dae464372..c63659cb5b1b058bf0bfc616d74569886357bded 100644 --- a/src/db/sysdb_upgrade.c +++ b/src/db/sysdb_upgrade.c @@ -1584,6 +1584,57 @@ done: return ret; } +int sysdb_upgrade_16(struct sysdb_ctx *sysdb, const char **ver) +{ + struct ldb_message *msg; + struct upgrade_ctx *ctx; + errno_t ret; + + ret = commence_upgrade(sysdb, sysdb->ldb, SYSDB_VERSION_0_17, &ctx); + if (ret) { + return ret; + } + + /* add new indexes */ + msg = ldb_msg_new(ctx); + if (!msg) { + ret = ENOMEM; + goto done; + } + + msg->dn = ldb_dn_new(msg, sysdb->ldb, "@INDEXLIST"); + if (!msg->dn) { + ret = ENOMEM; + goto done; + } + + /* add index for cached */ + ret = ldb_msg_add_empty(msg, "@IDXATTR", LDB_FLAG_MOD_ADD, NULL); + if (ret != LDB_SUCCESS) { + ret = ENOMEM; + goto done; + } + + ret = ldb_msg_add_string(msg, "@IDXATTR", "cached"); + if (ret != LDB_SUCCESS) { + ret = ENOMEM; + goto done; + } + + ret = ldb_modify(sysdb->ldb, msg); + if (ret != LDB_SUCCESS) { + ret = sysdb_error_to_errno(ret); + goto done; + } + + /* conversion done, update version number */ + ret = update_version(ctx); + +done: + ret = finish_upgrade(ret, &ctx, ver); + return ret; +} + /* * Example template for future upgrades. * Copy and change version numbers as appropriate. diff --git a/src/responder/ifp/ifp_cache.c b/src/responder/ifp/ifp_cache.c new file mode 100644 index 0000000000000000000000000000000000000000..498e75595edb114ccde7c0fec9dc689a2d8fd82d --- /dev/null +++ b/src/responder/ifp/ifp_cache.c @@ -0,0 +1,305 @@ +/* + Authors: + Pavel BÅezina <pbrez...@redhat.com> + + Copyright (C) 2015 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 "db/sysdb.h" +#include "util/util.h" +#include "responder/common/responder.h" +#include "responder/ifp/ifp_cache.h" +#include "responder/ifp/ifp_users.h" +#include "responder/ifp/ifp_groups.h" +#include "responder/ifp/ifp_iface_generated.h" + +static struct ldb_dn * +ifp_cache_build_base_dn(TALLOC_CTX *mem_ctx, + enum ifp_cache_type type, + struct sss_domain_info *domain) +{ + struct ldb_dn *base_dn; + + switch (type) { + case IFP_CACHE_USER: + base_dn = sysdb_user_base_dn(mem_ctx, domain); + break; + case IFP_CACHE_GROUP: + base_dn = sysdb_group_base_dn(mem_ctx, domain); + break; + } + + return base_dn; +} + +static char * +ifp_cache_build_path(TALLOC_CTX *mem_ctx, + enum ifp_cache_type type, + struct sss_domain_info *domain, + struct ldb_message *msg) +{ + char *path; + + switch (type) { + case IFP_CACHE_USER: + path = ifp_users_build_path_from_msg(mem_ctx, domain, msg); + break; + case IFP_CACHE_GROUP: + path = ifp_groups_build_path_from_msg(mem_ctx, domain, msg); + break; + } + + return path; +} + +static const char * +ifp_cache_object_class(enum ifp_cache_type type) +{ + const char *class; + + switch (type) { + case IFP_CACHE_USER: + class = SYSDB_USER_CLASS; + break; + case IFP_CACHE_GROUP: + class = SYSDB_GROUP_CLASS; + break; + } + + return class; +} + +static errno_t +ifp_cache_get_cached_objects(TALLOC_CTX *mem_ctx, + enum ifp_cache_type type, + struct sss_domain_info *domain, + const char ***_paths, + int *_num_paths) +{ + TALLOC_CTX *tmp_ctx; + struct ldb_dn *base_dn; + struct ldb_result *result; + const char *class = ifp_cache_object_class(type); + const char **paths; + errno_t ret; + int ldb_ret; + int i; + const char *attrs[] = {SYSDB_OBJECTCLASS, SYSDB_UIDNUM, + SYSDB_GIDNUM, NULL}; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + base_dn = ifp_cache_build_base_dn(tmp_ctx, type, domain); + if (base_dn == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create base dn\n"); + ret = ENOMEM; + goto done; + } + + ldb_ret = ldb_search(sysdb_ctx_get_ldb(domain->sysdb), tmp_ctx, &result, + base_dn, LDB_SCOPE_SUBTREE, attrs, + "(&(objectClass=%s)(%s=TRUE))", class, SYSDB_CACHED); + if (ldb_ret != LDB_SUCCESS) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to search the cache\n"); + ret = EFAULT; + goto done; + } + + paths = talloc_zero_array(tmp_ctx, const char *, result->count + 1); + if (paths == NULL) { + ret = ENOMEM; + goto done; + } + + for (i = 0; i < result->count; i++) { + paths[i] = ifp_cache_build_path(paths, type, domain, result->msgs[i]); + if (paths[i] == NULL) { + ret = ENOMEM; + goto done; + } + } + + *_paths = talloc_steal(mem_ctx, paths); + *_num_paths = result->count; + + ret = EOK; + +done: + talloc_free(tmp_ctx); + return ret; +} + +int ifp_cache_list(struct sbus_request *sbus_req, + void *data, + enum ifp_cache_type type) +{ + DBusError *error; + struct sss_domain_info *domain; + struct ifp_ctx *ifp_ctx; + const char **tmp_paths; + int num_tmp_paths; + const char **paths; + int num_paths; + errno_t ret; + + ifp_ctx = talloc_get_type(data, struct ifp_ctx); + if (ifp_ctx == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n"); + return ERR_INTERNAL; + } + + domain = ifp_ctx->rctx->domains; + num_paths = 0; + paths = NULL; + while (domain != NULL) { + ret = ifp_cache_get_cached_objects(sbus_req, type, domain, + &tmp_paths, &num_tmp_paths); + if (ret != EOK) { + error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, + "Unable to build object list [%d]: %s\n", + ret, sss_strerror(ret)); + return sbus_request_fail_and_finish(sbus_req, error); + } + + ret = add_strings_lists(sbus_req, paths, tmp_paths, false, + discard_const(&paths)); + if (ret != EOK) { + error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, + "Unable to build object list [%d]: %s\n", + ret, sss_strerror(ret)); + return sbus_request_fail_and_finish(sbus_req, error); + } + + num_paths += num_tmp_paths; + + domain = get_next_domain(domain, true); + } + + iface_ifp_cache_List_finish(sbus_req, paths, num_paths); + + return EOK; +} + +int ifp_cache_list_by_domain(struct sbus_request *sbus_req, + void *data, + const char *domainname, + enum ifp_cache_type type) +{ + DBusError *error; + struct sss_domain_info *domain; + struct ifp_ctx *ifp_ctx; + const char **paths; + int num_paths; + errno_t ret; + + ifp_ctx = talloc_get_type(data, struct ifp_ctx); + if (ifp_ctx == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n"); + return ERR_INTERNAL; + } + + domain = find_domain_by_name(ifp_ctx->rctx->domains, domainname, true); + if (domain == NULL) { + error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, "Unknown domain"); + return sbus_request_fail_and_finish(sbus_req, error); + } + + ret = ifp_cache_get_cached_objects(sbus_req, type, domain, + &paths, &num_paths); + if (ret != EOK) { + error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, "Unable to build " + "object list [%d]: %s\n", ret, sss_strerror(ret)); + return sbus_request_fail_and_finish(sbus_req, error); + } + + iface_ifp_cache_ListByDomain_finish(sbus_req, paths, num_paths); + + return EOK; +} + +static errno_t ifp_cache_object_set(struct sss_domain_info *domain, + struct ldb_dn *dn, + bool value) +{ + struct sysdb_attrs *attrs; + errno_t ret; + + attrs = sysdb_new_attrs(NULL); + if (attrs == NULL) { + return ENOMEM; + } + + ret = sysdb_attrs_add_bool(attrs, SYSDB_CACHED, value); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to add attribute [%d]: %s\n", + ret, sss_strerror(ret)); + goto done; + } + + ret = sysdb_set_entry_attr(domain->sysdb, dn, attrs, SYSDB_MOD_REP); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to modify entry [%d]: %s\n", + ret, sss_strerror(ret)); + goto done; + } + + ret = EOK; + +done: + talloc_free(attrs); + + return ret; +} + +int ifp_cache_object_store(struct sbus_request *sbus_req, + struct sss_domain_info *domain, + struct ldb_dn *dn) +{ + errno_t ret; + + ret = ifp_cache_object_set(domain, dn, true); + + if (ret == EOK) { + iface_ifp_cache_object_Store_finish(sbus_req, true); + } else { + iface_ifp_cache_object_Store_finish(sbus_req, false); + } + + return EOK; +} + +int ifp_cache_object_remove(struct sbus_request *sbus_req, + struct sss_domain_info *domain, + struct ldb_dn *dn) +{ + errno_t ret; + + ret = ifp_cache_object_set(domain, dn, false); + + if (ret == EOK) { + iface_ifp_cache_object_Remove_finish(sbus_req, true); + } else { + iface_ifp_cache_object_Remove_finish(sbus_req, false); + } + + return EOK; +} diff --git a/src/responder/ifp/ifp_cache.h b/src/responder/ifp/ifp_cache.h new file mode 100644 index 0000000000000000000000000000000000000000..56e90bb9c791d5f63d98e8e94b83f3695d88c742 --- /dev/null +++ b/src/responder/ifp/ifp_cache.h @@ -0,0 +1,53 @@ +/* + Authors: + Pavel BÅezina <pbrez...@redhat.com> + + Copyright (C) 2015 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/>. +*/ + +#ifndef IFP_CACHE_H_ +#define IFP_CACHE_H_ + +#include "responder/common/responder.h" +#include "responder/ifp/ifp_iface_generated.h" + +/* org.freedesktop-sssd-infopipe.Cache */ + +enum ifp_cache_type { + IFP_CACHE_USER, + IFP_CACHE_GROUP +}; + +int ifp_cache_list(struct sbus_request *sbus_req, + void *data, + enum ifp_cache_type type); + +int ifp_cache_list_by_domain(struct sbus_request *sbus_req, + void *data, + const char *domain, + enum ifp_cache_type type); + +/* org.freedesktop-sssd-infopipe.Cache.Object */ + +int ifp_cache_object_store(struct sbus_request *sbus_req, + struct sss_domain_info *domain, + struct ldb_dn *dn); + +int ifp_cache_object_remove(struct sbus_request *sbus_req, + struct sss_domain_info *domain, + struct ldb_dn *dn); + +#endif /* IFP_CACHE_H_ */ diff --git a/src/responder/ifp/ifp_groups.c b/src/responder/ifp/ifp_groups.c index f1f86ce1ae29aaa906c2ebd56b81476ce18dfa1a..1b581b568f14362a47b4a80eb55d2de8eb936ae3 100644 --- a/src/responder/ifp/ifp_groups.c +++ b/src/responder/ifp/ifp_groups.c @@ -29,6 +29,7 @@ #include "responder/common/responder_cache_req.h" #include "responder/ifp/ifp_groups.h" #include "responder/ifp/ifp_users.h" +#include "responder/ifp/ifp_cache.h" char * ifp_groups_build_path_from_msg(TALLOC_CTX *mem_ctx, struct sss_domain_info *domain, @@ -720,3 +721,54 @@ void ifp_groups_group_get_groups(struct sbus_request *sbus_req, DEBUG(SSSDBG_CRIT_FAILURE, "Unable to acquire groups members\n"); } } + +int ifp_cache_list_group(struct sbus_request *sbus_req, + void *data) +{ + return ifp_cache_list(sbus_req, data, IFP_CACHE_GROUP); +} + +int ifp_cache_list_by_domain_group(struct sbus_request *sbus_req, + void *data, + const char *domain) +{ + return ifp_cache_list_by_domain(sbus_req, data, domain, IFP_CACHE_GROUP); +} + +int ifp_cache_object_store_group(struct sbus_request *sbus_req, + void *data) +{ + DBusError *error; + struct sss_domain_info *domain; + struct ldb_message *group; + errno_t ret; + + ret = ifp_groups_group_get(sbus_req, data, NULL, &domain, &group); + if (ret != EOK) { + error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, "Failed to fetch " + "group [%d]: %s\n", ret, sss_strerror(ret)); + return sbus_request_fail_and_finish(sbus_req, error); + } + + /* The request is finished inside. */ + return ifp_cache_object_store(sbus_req, domain, group->dn); +} + +int ifp_cache_object_remove_group(struct sbus_request *sbus_req, + void *data) +{ + DBusError *error; + struct sss_domain_info *domain; + struct ldb_message *group; + errno_t ret; + + ret = ifp_groups_group_get(sbus_req, data, NULL, &domain, &group); + if (ret != EOK) { + error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, "Failed to fetch " + "group [%d]: %s\n", ret, sss_strerror(ret)); + return sbus_request_fail_and_finish(sbus_req, error); + } + + /* The request is finished inside. */ + return ifp_cache_object_remove(sbus_req, domain, group->dn); +} diff --git a/src/responder/ifp/ifp_groups.h b/src/responder/ifp/ifp_groups.h index 0474ca44f19cb847ed803d0681f5aac19e55be4a..09c5a1c88d7f8df3c6917e62ba3e7224b990edfc 100644 --- a/src/responder/ifp/ifp_groups.h +++ b/src/responder/ifp/ifp_groups.h @@ -77,4 +77,21 @@ void ifp_groups_group_get_groups(struct sbus_request *sbus_req, const char ***_out, int *_size); +/* org.freedesktop.sssd.infopipe.Cache */ + +int ifp_cache_list_group(struct sbus_request *sbus_req, + void *data); + +int ifp_cache_list_by_domain_group(struct sbus_request *sbus_req, + void *data, + const char *domain); + +/* org.freedesktop.sssd.infopipe.Cache.Object */ + +int ifp_cache_object_store_group(struct sbus_request *sbus_req, + void *data); + +int ifp_cache_object_remove_group(struct sbus_request *sbus_req, + void *data); + #endif /* IFP_GROUPS_H_ */ diff --git a/src/responder/ifp/ifp_iface.c b/src/responder/ifp/ifp_iface.c index ce987b6075ee886e7608455600e0a788c30c9741..015c66dc5323e237dd21575162e434b11acd8ed7 100644 --- a/src/responder/ifp/ifp_iface.c +++ b/src/responder/ifp/ifp_iface.c @@ -116,6 +116,30 @@ struct iface_ifp_groups_group iface_ifp_groups_group = { .get_groups = ifp_groups_group_get_groups }; +struct iface_ifp_cache iface_ifp_cache_user = { + { &iface_ifp_cache_meta, 0 }, + .List = ifp_cache_list_user, + .ListByDomain = ifp_cache_list_by_domain_user +}; + +struct iface_ifp_cache_object iface_ifp_cache_object_user = { + { &iface_ifp_cache_object_meta, 0 }, + .Store = ifp_cache_object_store_user, + .Remove = ifp_cache_object_remove_user +}; + +struct iface_ifp_cache iface_ifp_cache_group = { + { &iface_ifp_cache_meta, 0 }, + .List = ifp_cache_list_group, + .ListByDomain = ifp_cache_list_by_domain_group +}; + +struct iface_ifp_cache_object iface_ifp_cache_object_group = { + { &iface_ifp_cache_object_meta, 0 }, + .Store = ifp_cache_object_store_group, + .Remove = ifp_cache_object_remove_group +}; + struct iface_map { const char *path; struct sbus_vtable *vtable; @@ -126,9 +150,13 @@ static struct iface_map iface_map[] = { { IFP_PATH_DOMAINS_TREE, &iface_ifp_domains.vtable }, { IFP_PATH_COMPONENTS_TREE, &iface_ifp_components.vtable }, { IFP_PATH_USERS, &iface_ifp_users.vtable }, + { IFP_PATH_USERS, &iface_ifp_cache_user.vtable }, { IFP_PATH_USERS_TREE, &iface_ifp_users_user.vtable }, + { IFP_PATH_USERS_TREE, &iface_ifp_cache_object_user.vtable }, { IFP_PATH_GROUPS, &iface_ifp_groups.vtable }, + { IFP_PATH_GROUPS, &iface_ifp_cache_group.vtable }, { IFP_PATH_GROUPS_TREE, &iface_ifp_groups_group.vtable }, + { IFP_PATH_GROUPS_TREE, &iface_ifp_cache_object_group.vtable }, { NULL, NULL }, }; diff --git a/src/responder/ifp/ifp_iface.xml b/src/responder/ifp/ifp_iface.xml index fbd3d3f5ac812a21c8768e28188217edbc83300b..340eb6d23ebfebb508e12118b9ac6c9a71fed099 100644 --- a/src/responder/ifp/ifp_iface.xml +++ b/src/responder/ifp/ifp_iface.xml @@ -101,6 +101,29 @@ <property name="subdomain" type="b" access="read"/> <property name="parent_domain" type="o" access="read"/> </interface> + + <interface name="org.freedesktop.sssd.infopipe.Cache"> + <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="iface_ifp_cache"/> + + <method name="List"> + <arg name="result" type="ao" direction="out" /> + </method> + <method name="ListByDomain"> + <arg name="domain_name" type="s" direction="in" /> + <arg name="result" type="ao" direction="out"/> + </method> + </interface> + + <interface name="org.freedesktop.sssd.infopipe.Cache.Object"> + <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="iface_ifp_cache_object"/> + + <method name="Store"> + <arg name="result" type="b" direction="out" /> + </method> + <method name="Remove"> + <arg name="result" type="b" direction="out" /> + </method> + </interface> <interface name="org.freedesktop.sssd.infopipe.Users"> <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="iface_ifp_users"/> diff --git a/src/responder/ifp/ifp_iface_generated.c b/src/responder/ifp/ifp_iface_generated.c index ff00be8eaaedc28e37d39cdc85262c8041dafa0b..8255cbea729d9b2c0696cbfdef5c0daf9d958631 100644 --- a/src/responder/ifp/ifp_iface_generated.c +++ b/src/responder/ifp/ifp_iface_generated.c @@ -531,6 +531,122 @@ const struct sbus_interface_meta iface_ifp_domains_meta = { sbus_invoke_get_all, /* GetAll invoker */ }; +/* arguments for org.freedesktop.sssd.infopipe.Cache.List */ +const struct sbus_arg_meta iface_ifp_cache_List__out[] = { + { "result", "ao" }, + { NULL, } +}; + +int iface_ifp_cache_List_finish(struct sbus_request *req, const char *arg_result[], int len_result) +{ + return sbus_request_return_and_finish(req, + DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, &arg_result, len_result, + DBUS_TYPE_INVALID); +} + +/* arguments for org.freedesktop.sssd.infopipe.Cache.ListByDomain */ +const struct sbus_arg_meta iface_ifp_cache_ListByDomain__in[] = { + { "domain_name", "s" }, + { NULL, } +}; + +/* arguments for org.freedesktop.sssd.infopipe.Cache.ListByDomain */ +const struct sbus_arg_meta iface_ifp_cache_ListByDomain__out[] = { + { "result", "ao" }, + { NULL, } +}; + +int iface_ifp_cache_ListByDomain_finish(struct sbus_request *req, const char *arg_result[], int len_result) +{ + return sbus_request_return_and_finish(req, + DBUS_TYPE_ARRAY, DBUS_TYPE_OBJECT_PATH, &arg_result, len_result, + DBUS_TYPE_INVALID); +} + +/* methods for org.freedesktop.sssd.infopipe.Cache */ +const struct sbus_method_meta iface_ifp_cache__methods[] = { + { + "List", /* name */ + NULL, /* no in_args */ + iface_ifp_cache_List__out, + offsetof(struct iface_ifp_cache, List), + NULL, /* no invoker */ + }, + { + "ListByDomain", /* name */ + iface_ifp_cache_ListByDomain__in, + iface_ifp_cache_ListByDomain__out, + offsetof(struct iface_ifp_cache, ListByDomain), + invoke_s_method, + }, + { NULL, } +}; + +/* interface info for org.freedesktop.sssd.infopipe.Cache */ +const struct sbus_interface_meta iface_ifp_cache_meta = { + "org.freedesktop.sssd.infopipe.Cache", /* name */ + iface_ifp_cache__methods, + NULL, /* no signals */ + NULL, /* no properties */ + sbus_invoke_get_all, /* GetAll invoker */ +}; + +/* arguments for org.freedesktop.sssd.infopipe.Cache.Object.Store */ +const struct sbus_arg_meta iface_ifp_cache_object_Store__out[] = { + { "result", "b" }, + { NULL, } +}; + +int iface_ifp_cache_object_Store_finish(struct sbus_request *req, bool arg_result) +{ + dbus_bool_t cast_result = arg_result; + return sbus_request_return_and_finish(req, + DBUS_TYPE_BOOLEAN, &cast_result, + DBUS_TYPE_INVALID); +} + +/* arguments for org.freedesktop.sssd.infopipe.Cache.Object.Remove */ +const struct sbus_arg_meta iface_ifp_cache_object_Remove__out[] = { + { "result", "b" }, + { NULL, } +}; + +int iface_ifp_cache_object_Remove_finish(struct sbus_request *req, bool arg_result) +{ + dbus_bool_t cast_result = arg_result; + return sbus_request_return_and_finish(req, + DBUS_TYPE_BOOLEAN, &cast_result, + DBUS_TYPE_INVALID); +} + +/* methods for org.freedesktop.sssd.infopipe.Cache.Object */ +const struct sbus_method_meta iface_ifp_cache_object__methods[] = { + { + "Store", /* name */ + NULL, /* no in_args */ + iface_ifp_cache_object_Store__out, + offsetof(struct iface_ifp_cache_object, Store), + NULL, /* no invoker */ + }, + { + "Remove", /* name */ + NULL, /* no in_args */ + iface_ifp_cache_object_Remove__out, + offsetof(struct iface_ifp_cache_object, Remove), + NULL, /* no invoker */ + }, + { NULL, } +}; + +/* interface info for org.freedesktop.sssd.infopipe.Cache.Object */ +const struct sbus_interface_meta iface_ifp_cache_object_meta = { + "org.freedesktop.sssd.infopipe.Cache.Object", /* name */ + iface_ifp_cache_object__methods, + NULL, /* no signals */ + NULL, /* no properties */ + sbus_invoke_get_all, /* GetAll invoker */ +}; + /* arguments for org.freedesktop.sssd.infopipe.Users.FindByName */ const struct sbus_arg_meta iface_ifp_users_FindByName__in[] = { { "name", "s" }, diff --git a/src/responder/ifp/ifp_iface_generated.h b/src/responder/ifp/ifp_iface_generated.h index 1bd2a448f3ee9af73091bd991a27f6b60f07a579..d2e5cdd3a689d42509e63adde70237cbde627ee2 100644 --- a/src/responder/ifp/ifp_iface_generated.h +++ b/src/responder/ifp/ifp_iface_generated.h @@ -54,6 +54,16 @@ #define IFACE_IFP_DOMAINS_SUBDOMAIN "subdomain" #define IFACE_IFP_DOMAINS_PARENT_DOMAIN "parent_domain" +/* constants for org.freedesktop.sssd.infopipe.Cache */ +#define IFACE_IFP_CACHE "org.freedesktop.sssd.infopipe.Cache" +#define IFACE_IFP_CACHE_LIST "List" +#define IFACE_IFP_CACHE_LISTBYDOMAIN "ListByDomain" + +/* constants for org.freedesktop.sssd.infopipe.Cache.Object */ +#define IFACE_IFP_CACHE_OBJECT "org.freedesktop.sssd.infopipe.Cache.Object" +#define IFACE_IFP_CACHE_OBJECT_STORE "Store" +#define IFACE_IFP_CACHE_OBJECT_REMOVE "Remove" + /* constants for org.freedesktop.sssd.infopipe.Users */ #define IFACE_IFP_USERS "org.freedesktop.sssd.infopipe.Users" #define IFACE_IFP_USERS_FINDBYNAME "FindByName" @@ -194,6 +204,32 @@ struct iface_ifp_domains { void (*get_parent_domain)(struct sbus_request *, void *data, const char **); }; +/* vtable for org.freedesktop.sssd.infopipe.Cache */ +struct iface_ifp_cache { + struct sbus_vtable vtable; /* derive from sbus_vtable */ + int (*List)(struct sbus_request *req, void *data); + int (*ListByDomain)(struct sbus_request *req, void *data, const char *arg_domain_name); +}; + +/* finish function for List */ +int iface_ifp_cache_List_finish(struct sbus_request *req, const char *arg_result[], int len_result); + +/* finish function for ListByDomain */ +int iface_ifp_cache_ListByDomain_finish(struct sbus_request *req, const char *arg_result[], int len_result); + +/* vtable for org.freedesktop.sssd.infopipe.Cache.Object */ +struct iface_ifp_cache_object { + struct sbus_vtable vtable; /* derive from sbus_vtable */ + int (*Store)(struct sbus_request *req, void *data); + int (*Remove)(struct sbus_request *req, void *data); +}; + +/* finish function for Store */ +int iface_ifp_cache_object_Store_finish(struct sbus_request *req, bool arg_result); + +/* finish function for Remove */ +int iface_ifp_cache_object_Remove_finish(struct sbus_request *req, bool arg_result); + /* vtable for org.freedesktop.sssd.infopipe.Users */ struct iface_ifp_users { struct sbus_vtable vtable; /* derive from sbus_vtable */ @@ -285,6 +321,12 @@ extern const struct sbus_interface_meta iface_ifp_components_meta; /* interface info for org.freedesktop.sssd.infopipe.Domains */ extern const struct sbus_interface_meta iface_ifp_domains_meta; +/* interface info for org.freedesktop.sssd.infopipe.Cache */ +extern const struct sbus_interface_meta iface_ifp_cache_meta; + +/* interface info for org.freedesktop.sssd.infopipe.Cache.Object */ +extern const struct sbus_interface_meta iface_ifp_cache_object_meta; + /* interface info for org.freedesktop.sssd.infopipe.Users */ extern const struct sbus_interface_meta iface_ifp_users_meta; diff --git a/src/responder/ifp/ifp_users.c b/src/responder/ifp/ifp_users.c index 26c1aa696e5fbc3856ff45b0eb2c88d6bfbd2340..fa6f47f0d2f7ce52c3f0069b8ebf0bf1c98dbf22 100644 --- a/src/responder/ifp/ifp_users.c +++ b/src/responder/ifp/ifp_users.c @@ -30,6 +30,7 @@ #include "responder/common/responder_cache_req.h" #include "responder/ifp/ifp_users.h" #include "responder/ifp/ifp_groups.h" +#include "responder/ifp/ifp_cache.h" char * ifp_users_build_path_from_msg(TALLOC_CTX *mem_ctx, struct sss_domain_info *domain, @@ -659,3 +660,54 @@ void ifp_users_user_get_extra_attributes(struct sbus_request *sbus_req, *_out = table; } + +int ifp_cache_list_user(struct sbus_request *sbus_req, + void *data) +{ + return ifp_cache_list(sbus_req, data, IFP_CACHE_USER); +} + +int ifp_cache_list_by_domain_user(struct sbus_request *sbus_req, + void *data, + const char *domain) +{ + return ifp_cache_list_by_domain(sbus_req, data, domain, IFP_CACHE_USER); +} + +int ifp_cache_object_store_user(struct sbus_request *sbus_req, + void *data) +{ + DBusError *error; + struct sss_domain_info *domain; + struct ldb_message *user; + errno_t ret; + + ret = ifp_users_user_get(sbus_req, data, NULL, &domain, &user); + if (ret != EOK) { + error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, "Failed to fetch " + "user [%d]: %s\n", ret, sss_strerror(ret)); + return sbus_request_fail_and_finish(sbus_req, error); + } + + /* The request is finished inside. */ + return ifp_cache_object_store(sbus_req, domain, user->dn); +} + +int ifp_cache_object_remove_user(struct sbus_request *sbus_req, + void *data) +{ + DBusError *error; + struct sss_domain_info *domain; + struct ldb_message *user; + errno_t ret; + + ret = ifp_users_user_get(sbus_req, data, NULL, &domain, &user); + if (ret != EOK) { + error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, "Failed to fetch " + "user [%d]: %s\n", ret, sss_strerror(ret)); + return sbus_request_fail_and_finish(sbus_req, error); + } + + /* The request is finished inside. */ + return ifp_cache_object_remove(sbus_req, domain, user->dn); +} diff --git a/src/responder/ifp/ifp_users.h b/src/responder/ifp/ifp_users.h index 7027ef14e51e3ca2bd92368fdfc10315edbf2fa8..4da0a734752a2a1bd11b0e21c532a1302c9126f1 100644 --- a/src/responder/ifp/ifp_users.h +++ b/src/responder/ifp/ifp_users.h @@ -92,4 +92,21 @@ void ifp_users_user_get_extra_attributes(struct sbus_request *sbus_req, void *data, hash_table_t **_out); +/* org.freedesktop.sssd.infopipe.Cache */ + +int ifp_cache_list_user(struct sbus_request *sbus_req, + void *data); + +int ifp_cache_list_by_domain_user(struct sbus_request *sbus_req, + void *data, + const char *domain); + +/* org.freedesktop.sssd.infopipe.Cache.Object */ + +int ifp_cache_object_store_user(struct sbus_request *sbus_req, + void *data); + +int ifp_cache_object_remove_user(struct sbus_request *sbus_req, + void *data); + #endif /* IFP_USERS_H_ */ diff --git a/src/responder/ifp/org.freedesktop.sssd.infopipe.conf b/src/responder/ifp/org.freedesktop.sssd.infopipe.conf index b8df49350ecdd119fdde196a21771cae41dc52ef..398f303f75df49d159d8527c46459203b2210028 100644 --- a/src/responder/ifp/org.freedesktop.sssd.infopipe.conf +++ b/src/responder/ifp/org.freedesktop.sssd.infopipe.conf @@ -34,6 +34,8 @@ <allow send_interface="org.freedesktop.sssd.infopipe.Users.User"/> <allow send_interface="org.freedesktop.sssd.infopipe.Groups"/> <allow send_interface="org.freedesktop.sssd.infopipe.Groups.Group"/> + <allow send_interface="org.freedesktop.sssd.infopipe.Cache"/> + <allow send_interface="org.freedesktop.sssd.infopipe.Cache.Object"/> </policy> <policy user="root"> -- 2.1.0
From 3cd493aa2783f57eb8e8acb55d4129ddcfac47de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrez...@redhat.com> Date: Wed, 20 May 2015 13:34:46 +0200 Subject: [PATCH 2/4] SBUS: Use default GetAll invoker if none is set It is alright for an interface to not have any GetAll invoker set if it doesn't have any properties, but we still want to return an empty message. --- src/sbus/sssd_dbus_properties.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/sbus/sssd_dbus_properties.c b/src/sbus/sssd_dbus_properties.c index 25ea446d16701d2ebd2c034b37728482207a4ddf..6b4ca74bad840eb7ae2b9044792facf55ff1e542 100644 --- a/src/sbus/sssd_dbus_properties.c +++ b/src/sbus/sssd_dbus_properties.c @@ -332,7 +332,14 @@ static int sbus_properties_get_all(struct sbus_request *sbus_req, void *pvt) goto fail; } - iface->vtable->meta->invoker_get_all(sbus_subreq); + if (iface->vtable->meta->invoker_get_all == NULL) { + DEBUG(SSSDBG_TRACE_FUNC, "No get all invoker set," + "using the default one\n"); + + sbus_invoke_get_all(sbus_req); + } else { + iface->vtable->meta->invoker_get_all(sbus_subreq); + } return EOK; -- 2.1.0
From 9c13aa15cbe377158356b7ec87e98c0fec0e5791 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrez...@redhat.com> Date: Wed, 20 May 2015 14:14:53 +0200 Subject: [PATCH 3/4] SBUS: Add support for <node /> in introspection --- src/sbus/sssd_dbus.h | 10 ++++ src/sbus/sssd_dbus_connection.c | 7 +++ src/sbus/sssd_dbus_interface.c | 115 ++++++++++++++++++++++++++++++++++++++++ src/sbus/sssd_dbus_introspect.c | 41 ++++++++++++-- src/sbus/sssd_dbus_private.h | 11 ++++ src/tests/sbus_tests.c | 2 +- 6 files changed, 181 insertions(+), 5 deletions(-) diff --git a/src/sbus/sssd_dbus.h b/src/sbus/sssd_dbus.h index 61c18ae28f4617239ed0e941f6cf5dd9fe0b24db..818070fa5eb28c8dc9bcb71ac0fb2008a10c454a 100644 --- a/src/sbus/sssd_dbus.h +++ b/src/sbus/sssd_dbus.h @@ -80,6 +80,10 @@ typedef void (*sbus_conn_reconn_callback_fn)(struct sbus_connection *, int, void */ typedef int (*sbus_server_conn_init_fn)(struct sbus_connection *, void *); +typedef const char ** (* sbus_nodes_fn)(TALLOC_CTX *mem_ctx, + const char *path, + void *data); + enum { SBUS_CONN_TYPE_PRIVATE = 1, SBUS_CONN_TYPE_SHARED, @@ -177,6 +181,12 @@ int sbus_conn_register_iface(struct sbus_connection *conn, const char *object_path, void *handler_data); +void +sbus_conn_register_nodes(struct sbus_connection *conn, + const char *path, + sbus_nodes_fn nodes_fn, + void *data); + errno_t sbus_conn_reregister_paths(struct sbus_connection *conn); diff --git a/src/sbus/sssd_dbus_connection.c b/src/sbus/sssd_dbus_connection.c index 8ff279c1bf5f20d5396e1e41c6a162328657091f..d0df95bb2e5d3bbdf75f71e84c1901a40171ed12 100644 --- a/src/sbus/sssd_dbus_connection.c +++ b/src/sbus/sssd_dbus_connection.c @@ -168,6 +168,13 @@ int sbus_init_connection(TALLOC_CTX *ctx, return EIO; } + ret = sbus_nodes_hash_init(conn, conn, &conn->nodes_fns); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Cannot create node functions hash table\n"); + talloc_free(conn); + return EIO; + } + ret = sss_hash_create(conn, 32, &conn->clients); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Cannot create clients hash table\n"); diff --git a/src/sbus/sssd_dbus_interface.c b/src/sbus/sssd_dbus_interface.c index 1651478a898e0272312dc910b66be40c1bace435..51b0bbf0c4c04f65309d87d78f43abaef7588e47 100644 --- a/src/sbus/sssd_dbus_interface.c +++ b/src/sbus/sssd_dbus_interface.c @@ -732,6 +732,106 @@ done: return ret; } +errno_t +sbus_nodes_hash_init(TALLOC_CTX *mem_ctx, + struct sbus_connection *conn, + hash_table_t **_table) +{ + return sss_hash_create_ex(mem_ctx, 10, _table, 0, 0, 0, 0, + NULL, conn); +} + +struct sbus_nodes_data { + sbus_nodes_fn nodes_fn; + void *handler_data; +}; + +static errno_t +sbus_nodes_hash_add(hash_table_t *table, + const char *object_path, + sbus_nodes_fn nodes_fn, + void *handler_data) +{ + TALLOC_CTX *tmp_ctx; + struct sbus_nodes_data *data; + hash_key_t key; + hash_value_t value; + errno_t ret; + bool has_key; + int hret; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + key.type = HASH_KEY_STRING; + key.str = talloc_strdup(tmp_ctx, object_path); + if (key.str == NULL) { + return ENOMEM; + } + + has_key = hash_has_key(table, &key); + if (has_key) { + ret = EEXIST; + goto done; + } + + data = talloc_zero(tmp_ctx, struct sbus_nodes_data); + if (data == NULL) { + ret = ENOMEM; + goto done; + } + + data->handler_data = handler_data; + data->nodes_fn = nodes_fn; + + value.type = HASH_VALUE_PTR; + value.ptr = data; + + hret = hash_enter(table, &key, &value); + if (hret != HASH_SUCCESS) { + ret = EIO; + goto done; + } + + talloc_steal(table, key.str); + talloc_steal(table, data); + + ret = EOK; + +done: + talloc_free(tmp_ctx); + return ret; +} + +const char ** +sbus_nodes_hash_lookup(TALLOC_CTX *mem_ctx, + hash_table_t *table, + const char *object_path) +{ + struct sbus_nodes_data *data; + hash_key_t key; + hash_value_t value; + int hret; + + key.type = HASH_KEY_STRING; + key.str = discard_const(object_path); + + hret = hash_lookup(table, &key, &value); + if (hret == HASH_ERROR_KEY_NOT_FOUND) { + return NULL; + } else if (hret != HASH_SUCCESS) { + DEBUG(SSSDBG_OP_FAILURE, + "Unable to search hash table: hret=%d\n", hret); + return NULL; + } + + data = (struct sbus_nodes_data *)(value.ptr); + + return data->nodes_fn(mem_ctx, object_path, data->handler_data); +} + static struct sbus_interface * sbus_new_interface(TALLOC_CTX *mem_ctx, const char *object_path, @@ -870,6 +970,21 @@ sbus_conn_register_iface(struct sbus_connection *conn, return ret; } +void +sbus_conn_register_nodes(struct sbus_connection *conn, + const char *path, + sbus_nodes_fn nodes_fn, + void *data) +{ + errno_t ret; + + ret = sbus_nodes_hash_add(conn->nodes_fns, path, nodes_fn, data); + if (ret != EOK && ret != EEXIST) { + DEBUG(SSSDBG_MINOR_FAILURE, "Unable to register node function with " + "%s. Introspection may not work correctly.\n", path); + } +} + errno_t sbus_conn_reregister_paths(struct sbus_connection *conn) { diff --git a/src/sbus/sssd_dbus_introspect.c b/src/sbus/sssd_dbus_introspect.c index 34279c8d4f398287c4bd4e1e81be47aaa79c1dd4..a66432dd97fecea81e9f5f543bba6ca6a9a13107 100644 --- a/src/sbus/sssd_dbus_introspect.c +++ b/src/sbus/sssd_dbus_introspect.c @@ -34,7 +34,7 @@ "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n" \ " \"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n" -#define FMT_NODE "<node>\n" +#define FMT_NODE "<node name=\"%s\">\n" #define FMT_IFACE " <interface name=\"%s\">\n" #define FMT_METHOD " <method name=\"%s\">\n" #define FMT_METHOD_NOARG " <method name=\"%s\" />\n" @@ -46,6 +46,7 @@ #define FMT_SIGNAL_CLOSE " </signal>\n" #define FMT_PROPERTY " <property name=\"%s\" type=\"%s\" access=\"%s\" />\n" #define FMT_IFACE_CLOSE " </interface>\n" +#define FMT_CHILD_NODE " <node name=\"%s\" />\n" #define FMT_NODE_CLOSE "</node>\n" #define WRITE_OR_FAIL(file, ret, label, fmt, ...) do { \ @@ -294,8 +295,31 @@ done: return ret; } +static int +sbus_introspect_generate_nodes(FILE *file, const char **nodes) +{ + int ret; + int i; + + if (nodes == NULL) { + return EOK; + } + + for (i = 0; nodes[i] != NULL; i++) { + WRITE_OR_FAIL(file, ret, done, FMT_CHILD_NODE, nodes[i]); + } + + ret = EOK; + +done: + return ret; +} + static char * -sbus_introspect_generate(TALLOC_CTX *mem_ctx, struct sbus_interface_list *list) +sbus_introspect_generate(TALLOC_CTX *mem_ctx, + const char *node, + const char **nodes, + struct sbus_interface_list *list) { struct sbus_interface_list *item; char *introspect = NULL; @@ -310,7 +334,7 @@ sbus_introspect_generate(TALLOC_CTX *mem_ctx, struct sbus_interface_list *list) } WRITE_OR_FAIL(memstream, ret, done, FMT_DOCTYPE); - WRITE_OR_FAIL(memstream, ret, done, FMT_NODE); + WRITE_OR_FAIL(memstream, ret, done, FMT_NODE, node); DLIST_FOR_EACH(item, list) { ret = sbus_introspect_generate_iface(memstream, item->interface); @@ -319,6 +343,11 @@ sbus_introspect_generate(TALLOC_CTX *mem_ctx, struct sbus_interface_list *list) } } + ret = sbus_introspect_generate_nodes(memstream, nodes); + if (ret != EOK) { + goto done; + } + WRITE_OR_FAIL(memstream, ret, done, FMT_NODE_CLOSE); fflush(memstream); @@ -341,6 +370,7 @@ sbus_introspect(struct sbus_request *sbus_req, void *pvt) DBusError *error; struct sbus_interface_list *list; struct sbus_connection *conn; + const char **nodes; char *introspect; errno_t ret; @@ -354,7 +384,10 @@ sbus_introspect(struct sbus_request *sbus_req, void *pvt) return sbus_request_fail_and_finish(sbus_req, error); } - introspect = sbus_introspect_generate(sbus_req, list); + nodes = sbus_nodes_hash_lookup(sbus_req, conn->nodes_fns, sbus_req->path); + + introspect = sbus_introspect_generate(sbus_req, sbus_req->path, + nodes, list); if (introspect == NULL) { ret = ENOMEM; goto done; diff --git a/src/sbus/sssd_dbus_private.h b/src/sbus/sssd_dbus_private.h index 24b6bec18cf8331942480312505b2dce77d2c2ac..0493e1536573051d22f3c4b0ba50c977fcf7e269 100644 --- a/src/sbus/sssd_dbus_private.h +++ b/src/sbus/sssd_dbus_private.h @@ -48,6 +48,7 @@ struct sbus_connection { int disconnect; hash_table_t *managed_paths; + hash_table_t *nodes_fns; /* reconnect settings */ int retries; @@ -129,6 +130,16 @@ sbus_opath_hash_lookup_supported(TALLOC_CTX *mem_ctx, const char *object_path, struct sbus_interface_list **_list); +errno_t +sbus_nodes_hash_init(TALLOC_CTX *mem_ctx, + struct sbus_connection *conn, + hash_table_t **_table); + +const char ** +sbus_nodes_hash_lookup(TALLOC_CTX *mem_ctx, + hash_table_t *table, + const char *object_path); + void sbus_request_invoke_or_finish(struct sbus_request *dbus_req, sbus_msg_handler_fn handler_fn, diff --git a/src/tests/sbus_tests.c b/src/tests/sbus_tests.c index 47d0556cfd42acb98be5a3dc977e3d4f3ad671f4..598cc536db436032b6d14c6515cd411b1bd2279e 100644 --- a/src/tests/sbus_tests.c +++ b/src/tests/sbus_tests.c @@ -47,7 +47,7 @@ #define PILOT_IFACE_INTROSPECT \ "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n" \ " \"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n" \ - "<node>\n" \ + "<node name=\"/test/leela\">\n" \ " <interface name=\"org.freedesktop.DBus.Introspectable\">\n" \ " <method name=\"Introspect\">\n" \ " <arg type=\"s\" name=\"data\" direction=\"out\" />\n" \ -- 2.1.0
From 745f2a915c6920333c0c5594ab0ab1b37d81dabf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrez...@redhat.com> Date: Wed, 20 May 2015 14:45:25 +0200 Subject: [PATCH 4/4] IFP: Export nodes IFP now exports cached users and groups in introspection. --- Makefile.am | 1 + src/responder/ifp/ifp_cache.c | 78 ++++++++++++++++------ src/responder/ifp/ifp_cache.h | 10 ++- src/responder/ifp/ifp_iface_nodes.c | 129 ++++++++++++++++++++++++++++++++++++ src/responder/ifp/ifp_private.h | 2 + src/responder/ifp/ifpsrv.c | 2 + 6 files changed, 200 insertions(+), 22 deletions(-) create mode 100644 src/responder/ifp/ifp_iface_nodes.c diff --git a/Makefile.am b/Makefile.am index de0cf9738ad399eb8ebce8968082a7dc1913d06a..31f420ad5b47c11436cde94bd0fff5e87e974b29 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1086,6 +1086,7 @@ sssd_ifp_SOURCES = \ src/responder/ifp/ifp_iface_generated.c \ src/responder/ifp/ifp_iface_generated.h \ src/responder/ifp/ifp_iface.c \ + src/responder/ifp/ifp_iface_nodes.c \ src/responder/ifp/ifpsrv_util.c \ src/responder/ifp/ifp_domains.c \ src/responder/ifp/ifp_components.c \ diff --git a/src/responder/ifp/ifp_cache.c b/src/responder/ifp/ifp_cache.c index 498e75595edb114ccde7c0fec9dc689a2d8fd82d..97e8e26c4aabe41975b8ef1286773ec10c0c9134 100644 --- a/src/responder/ifp/ifp_cache.c +++ b/src/responder/ifp/ifp_cache.c @@ -148,45 +148,43 @@ done: return ret; } -int ifp_cache_list(struct sbus_request *sbus_req, - void *data, - enum ifp_cache_type type) +errno_t ifp_cache_list_domains(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domains, + enum ifp_cache_type type, + const char ***_paths, + int *_num_paths) { - DBusError *error; + TALLOC_CTX *tmp_ctx; struct sss_domain_info *domain; - struct ifp_ctx *ifp_ctx; const char **tmp_paths; int num_tmp_paths; const char **paths; int num_paths; errno_t ret; - ifp_ctx = talloc_get_type(data, struct ifp_ctx); - if (ifp_ctx == NULL) { - DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n"); - return ERR_INTERNAL; + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + return ENOMEM; } - domain = ifp_ctx->rctx->domains; + domain = domains; num_paths = 0; paths = NULL; while (domain != NULL) { - ret = ifp_cache_get_cached_objects(sbus_req, type, domain, + ret = ifp_cache_get_cached_objects(tmp_ctx, type, domain, &tmp_paths, &num_tmp_paths); if (ret != EOK) { - error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, - "Unable to build object list [%d]: %s\n", - ret, sss_strerror(ret)); - return sbus_request_fail_and_finish(sbus_req, error); + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to build object list " + "[%d]: %s\n", ret, sss_strerror(ret)); + goto done; } - ret = add_strings_lists(sbus_req, paths, tmp_paths, false, + ret = add_strings_lists(tmp_ctx, paths, tmp_paths, true, discard_const(&paths)); if (ret != EOK) { - error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, - "Unable to build object list [%d]: %s\n", - ret, sss_strerror(ret)); - return sbus_request_fail_and_finish(sbus_req, error); + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to build object list " + "[%d]: %s\n", ret, sss_strerror(ret)); + goto done; } num_paths += num_tmp_paths; @@ -194,6 +192,46 @@ int ifp_cache_list(struct sbus_request *sbus_req, domain = get_next_domain(domain, true); } + if (_paths != NULL) { + *_paths = talloc_steal(mem_ctx, paths); + } + + if (_num_paths != NULL) { + *_num_paths = num_paths; + } + + ret = EOK; + +done: + talloc_free(tmp_ctx); + return ret; +} + +int ifp_cache_list(struct sbus_request *sbus_req, + void *data, + enum ifp_cache_type type) +{ + DBusError *error; + struct ifp_ctx *ifp_ctx; + const char **paths; + int num_paths; + errno_t ret; + + ifp_ctx = talloc_get_type(data, struct ifp_ctx); + if (ifp_ctx == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n"); + return ERR_INTERNAL; + } + + ret = ifp_cache_list_domains(sbus_req, ifp_ctx->rctx->domains, type, + &paths, &num_paths); + if (ret != EOK) { + error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, + "Unable to build object list [%d]: %s\n", + ret, sss_strerror(ret)); + return sbus_request_fail_and_finish(sbus_req, error); + } + iface_ifp_cache_List_finish(sbus_req, paths, num_paths); return EOK; diff --git a/src/responder/ifp/ifp_cache.h b/src/responder/ifp/ifp_cache.h index 56e90bb9c791d5f63d98e8e94b83f3695d88c742..eb16309543d938b94d8c8fde18bfb30709f8e975 100644 --- a/src/responder/ifp/ifp_cache.h +++ b/src/responder/ifp/ifp_cache.h @@ -24,13 +24,19 @@ #include "responder/common/responder.h" #include "responder/ifp/ifp_iface_generated.h" -/* org.freedesktop-sssd-infopipe.Cache */ - enum ifp_cache_type { IFP_CACHE_USER, IFP_CACHE_GROUP }; +errno_t ifp_cache_list_domains(TALLOC_CTX *mem_ctx, + struct sss_domain_info *domains, + enum ifp_cache_type type, + const char ***_paths, + int *_num_paths); + +/* org.freedesktop-sssd-infopipe.Cache */ + int ifp_cache_list(struct sbus_request *sbus_req, void *data, enum ifp_cache_type type); diff --git a/src/responder/ifp/ifp_iface_nodes.c b/src/responder/ifp/ifp_iface_nodes.c new file mode 100644 index 0000000000000000000000000000000000000000..ecb9ba32405b6a78904bcee70c02425c3bcc4cdd --- /dev/null +++ b/src/responder/ifp/ifp_iface_nodes.c @@ -0,0 +1,129 @@ +/* + Authors: + Pavel BÅezina <pbrez...@redhat.com> + + Copyright (C) 2015 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 "sbus/sssd_dbus.h" +#include "responder/ifp/ifp_iface_generated.h" +#include "responder/ifp/ifp_users.h" +#include "responder/ifp/ifp_groups.h" +#include "responder/ifp/ifp_cache.h" + +static const char ** +nodes_ifp(TALLOC_CTX *mem_ctx, const char *path, void *data) +{ + static const char *nodes[] = {"Users", "Groups", NULL}; + + return nodes; +} + +static const char ** +nodes_cached_objects(TALLOC_CTX *mem_ctx, + void *data, + enum ifp_cache_type type, + const char *prefix) +{ + TALLOC_CTX *tmp_ctx; + struct ifp_ctx *ifp_ctx; + const char **paths; + const char **nodes; + const char *node; + int num_paths; + errno_t ret; + int i; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n"); + return NULL; + } + + ifp_ctx = talloc_get_type(data, struct ifp_ctx); + if (ifp_ctx == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n"); + goto fail; + } + + ret = ifp_cache_list_domains(tmp_ctx, ifp_ctx->rctx->domains, + type, &paths, &num_paths); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Unable to obtain cache objects list " + "[%d]: %s\n", ret, sss_strerror(ret)); + goto fail; + } + + nodes = talloc_zero_array(tmp_ctx, const char *, num_paths + 1); + if (nodes == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero_array() failed\n"); + goto fail; + } + + for (i = 0; i < num_paths; i++) { + node = sbus_opath_strip_prefix(paths[i], prefix); + nodes[i] = talloc_strdup(nodes, node); + if (nodes[i] == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup() failed\n"); + goto fail; + } + } + + talloc_steal(mem_ctx, nodes); + talloc_free(tmp_ctx); + + return nodes; + +fail: + talloc_free(tmp_ctx); + return NULL; +} + +static const char ** +nodes_users(TALLOC_CTX *mem_ctx, const char *path, void *data) +{ + return nodes_cached_objects(mem_ctx, data, IFP_CACHE_USER, + IFP_PATH_USERS "/"); +} + +static const char ** +nodes_groups(TALLOC_CTX *mem_ctx, const char *path, void *data) +{ + return nodes_cached_objects(mem_ctx, data, IFP_CACHE_GROUP, + IFP_PATH_GROUPS "/"); +} + +struct nodes_map { + const char *path; + sbus_nodes_fn fn; +}; + +static struct nodes_map nodes_map[] = { + { IFP_PATH, nodes_ifp }, + { IFP_PATH_USERS, nodes_users }, + { IFP_PATH_GROUPS, nodes_groups }, + { NULL, NULL} +}; + +void ifp_register_nodes(struct ifp_ctx *ctx, struct sbus_connection *conn) +{ + int i; + + for (i = 0; nodes_map[i].path != NULL; i++) { + sbus_conn_register_nodes(conn, nodes_map[i].path, + nodes_map[i].fn, ctx); + } +} diff --git a/src/responder/ifp/ifp_private.h b/src/responder/ifp/ifp_private.h index 94c9a4b85e2db7fd100dd7ea0b664081d6ba322e..304e4dc535aac4215cf318a0bea845c161c5f079 100644 --- a/src/responder/ifp/ifp_private.h +++ b/src/responder/ifp/ifp_private.h @@ -49,6 +49,8 @@ struct ifp_ctx { errno_t ifp_register_sbus_interface(struct sbus_connection *conn, void *handler_data); +void ifp_register_nodes(struct ifp_ctx *ctx, struct sbus_connection *conn); + /* This is a throwaway method to ease the review of the patch. * It will be removed later */ int ifp_ping(struct sbus_request *dbus_req, void *data); diff --git a/src/responder/ifp/ifpsrv.c b/src/responder/ifp/ifpsrv.c index f804ea1978b6b32590c67fa34e00f94008b7b423..631bcd266d7e06154dbf1f37f9f439119b2b8944 100644 --- a/src/responder/ifp/ifpsrv.c +++ b/src/responder/ifp/ifpsrv.c @@ -165,6 +165,8 @@ sysbus_init(TALLOC_CTX *mem_ctx, goto fail; } + ifp_register_nodes(pvt, system_bus->conn); + *sysbus = system_bus; return EOK; -- 2.1.0
_______________________________________________ sssd-devel mailing list sssd-devel@lists.fedorahosted.org https://lists.fedorahosted.org/mailman/listinfo/sssd-devel