summaryrefslogtreecommitdiffstats
path: root/src/responder
diff options
context:
space:
mode:
authorPavel Březina <pbrezina@redhat.com>2015-02-09 12:02:33 +0100
committerJakub Hrozek <jhrozek@redhat.com>2015-05-22 15:57:14 +0200
commita1e4113a5388e34c08459c5b69679c82ac2bddc9 (patch)
treede092388bfceb31b3038ce3cfb056cff6f31bf65 /src/responder
parentc747b0c875785ce693f70b50bdda0237c4b04e35 (diff)
downloadsssd-a1e4113a5388e34c08459c5b69679c82ac2bddc9.tar.gz
sssd-a1e4113a5388e34c08459c5b69679c82ac2bddc9.tar.xz
sssd-a1e4113a5388e34c08459c5b69679c82ac2bddc9.zip
IFP: add org.freedesktop.sssd.infopipe.Users.User
Example calls: dbus-send --print-reply --system --dest=org.freedesktop.sssd.infopipe /org/freedesktop/sssd/infopipe/Users/LDAP_2ePB/10001 org.freedesktop.DBus.Properties.Get string:org.freedesktop.sssd.infopipe.Users.User string:name method return sender=:1.159 -> dest=:1.165 reply_serial=2 variant string "user-1" Resolves: https://fedorahosted.org/sssd/ticket/2150 Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
Diffstat (limited to 'src/responder')
-rw-r--r--src/responder/ifp/ifp_groups.c39
-rw-r--r--src/responder/ifp/ifp_groups.h37
-rw-r--r--src/responder/ifp/ifp_iface.c14
-rw-r--r--src/responder/ifp/ifp_iface.xml15
-rw-r--r--src/responder/ifp/ifp_iface_generated.c104
-rw-r--r--src/responder/ifp/ifp_iface_generated.h70
-rw-r--r--src/responder/ifp/ifp_private.h10
-rw-r--r--src/responder/ifp/ifp_users.c459
-rw-r--r--src/responder/ifp/ifp_users.h38
-rw-r--r--src/responder/ifp/ifpsrv.c2
-rw-r--r--src/responder/ifp/ifpsrv_util.c91
-rw-r--r--src/responder/ifp/org.freedesktop.sssd.infopipe.conf1
12 files changed, 846 insertions, 34 deletions
diff --git a/src/responder/ifp/ifp_groups.c b/src/responder/ifp/ifp_groups.c
new file mode 100644
index 000000000..533e6806d
--- /dev/null
+++ b/src/responder/ifp/ifp_groups.c
@@ -0,0 +1,39 @@
+/*
+ Authors:
+ Pavel Březina <pbrezina@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 "db/sysdb.h"
+#include "responder/ifp/ifp_groups.h"
+
+char * ifp_groups_build_path_from_msg(TALLOC_CTX *mem_ctx,
+ struct sss_domain_info *domain,
+ struct ldb_message *msg)
+{
+ const char *gid;
+
+ gid = ldb_msg_find_attr_as_string(msg, SYSDB_GIDNUM, NULL);
+
+ if (gid == NULL) {
+ return NULL;
+ }
+
+ return sbus_opath_compose(mem_ctx, IFP_PATH_GROUPS, domain->name, gid);
+}
diff --git a/src/responder/ifp/ifp_groups.h b/src/responder/ifp/ifp_groups.h
new file mode 100644
index 000000000..1bdaf3e0c
--- /dev/null
+++ b/src/responder/ifp/ifp_groups.h
@@ -0,0 +1,37 @@
+/*
+ Authors:
+ Pavel Březina <pbrezina@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_GROUPS_H_
+#define IFP_GROUPS_H_
+
+#include "responder/ifp/ifp_iface_generated.h"
+#include "responder/ifp/ifp_private.h"
+
+#define IFP_PATH_GROUPS "/org/freedesktop/sssd/infopipe/Groups"
+#define IFP_PATH_GROUPS_TREE IFP_PATH_GROUPS SBUS_SUBTREE_SUFFIX
+
+/* Utility functions */
+
+char * ifp_groups_build_path_from_msg(TALLOC_CTX *mem_ctx,
+ struct sss_domain_info *domain,
+ struct ldb_message *msg);
+
+
+#endif /* IFP_GROUPS_H_ */
diff --git a/src/responder/ifp/ifp_iface.c b/src/responder/ifp/ifp_iface.c
index 753bad126..1878263c2 100644
--- a/src/responder/ifp/ifp_iface.c
+++ b/src/responder/ifp/ifp_iface.c
@@ -85,6 +85,19 @@ struct iface_ifp_users iface_ifp_users = {
.ListByDomainAndName = ifp_users_list_by_domain_and_name
};
+struct iface_ifp_users_user iface_ifp_users_user = {
+ { &iface_ifp_users_user_meta, 0 },
+ .UpdateGroupsList = ifp_users_user_update_groups_list,
+ .get_name = ifp_users_user_get_name,
+ .get_uidNumber = ifp_users_user_get_uid_number,
+ .get_gidNumber = ifp_users_user_get_gid_number,
+ .get_gecos = ifp_users_user_get_gecos,
+ .get_homeDirectory = ifp_users_user_get_home_directory,
+ .get_loginShell = ifp_users_user_get_login_shell,
+ .get_groups = ifp_users_user_get_groups,
+ .get_extraAttributes = ifp_users_user_get_extra_attributes
+};
+
struct iface_map {
const char *path;
struct sbus_vtable *vtable;
@@ -95,6 +108,7 @@ 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_TREE, &iface_ifp_users_user.vtable },
{ NULL, NULL },
};
diff --git a/src/responder/ifp/ifp_iface.xml b/src/responder/ifp/ifp_iface.xml
index d0c835949..2c15fddea 100644
--- a/src/responder/ifp/ifp_iface.xml
+++ b/src/responder/ifp/ifp_iface.xml
@@ -125,4 +125,19 @@
<arg name="result" type="ao" direction="out"/>
</method>
</interface>
+
+ <interface name="org.freedesktop.sssd.infopipe.Users.User">
+ <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="iface_ifp_users_user"/>
+
+ <method name="UpdateGroupsList" />
+
+ <property name="name" type="s" access="read" />
+ <property name="uidNumber" type="u" access="read" />
+ <property name="gidNumber" type="u" access="read" />
+ <property name="gecos" type="s" access="read" />
+ <property name="homeDirectory" type="s" access="read" />
+ <property name="loginShell" type="s" access="read" />
+ <property name="groups" type="ao" access="read" />
+ <property name="extraAttributes" type="a{sas}" access="read" />
+ </interface>
</node>
diff --git a/src/responder/ifp/ifp_iface_generated.c b/src/responder/ifp/ifp_iface_generated.c
index 40a416bc4..1f6c7ba1d 100644
--- a/src/responder/ifp/ifp_iface_generated.c
+++ b/src/responder/ifp/ifp_iface_generated.c
@@ -652,6 +652,110 @@ const struct sbus_interface_meta iface_ifp_users_meta = {
sbus_invoke_get_all, /* GetAll invoker */
};
+int iface_ifp_users_user_UpdateGroupsList_finish(struct sbus_request *req)
+{
+ return sbus_request_return_and_finish(req,
+ DBUS_TYPE_INVALID);
+}
+
+/* methods for org.freedesktop.sssd.infopipe.Users.User */
+const struct sbus_method_meta iface_ifp_users_user__methods[] = {
+ {
+ "UpdateGroupsList", /* name */
+ NULL, /* no in_args */
+ NULL, /* no out_args */
+ offsetof(struct iface_ifp_users_user, UpdateGroupsList),
+ NULL, /* no invoker */
+ },
+ { NULL, }
+};
+
+/* property info for org.freedesktop.sssd.infopipe.Users.User */
+const struct sbus_property_meta iface_ifp_users_user__properties[] = {
+ {
+ "name", /* name */
+ "s", /* type */
+ SBUS_PROPERTY_READABLE,
+ offsetof(struct iface_ifp_users_user, get_name),
+ sbus_invoke_get_s,
+ 0, /* not writable */
+ NULL, /* no invoker */
+ },
+ {
+ "uidNumber", /* name */
+ "u", /* type */
+ SBUS_PROPERTY_READABLE,
+ offsetof(struct iface_ifp_users_user, get_uidNumber),
+ sbus_invoke_get_u,
+ 0, /* not writable */
+ NULL, /* no invoker */
+ },
+ {
+ "gidNumber", /* name */
+ "u", /* type */
+ SBUS_PROPERTY_READABLE,
+ offsetof(struct iface_ifp_users_user, get_gidNumber),
+ sbus_invoke_get_u,
+ 0, /* not writable */
+ NULL, /* no invoker */
+ },
+ {
+ "gecos", /* name */
+ "s", /* type */
+ SBUS_PROPERTY_READABLE,
+ offsetof(struct iface_ifp_users_user, get_gecos),
+ sbus_invoke_get_s,
+ 0, /* not writable */
+ NULL, /* no invoker */
+ },
+ {
+ "homeDirectory", /* name */
+ "s", /* type */
+ SBUS_PROPERTY_READABLE,
+ offsetof(struct iface_ifp_users_user, get_homeDirectory),
+ sbus_invoke_get_s,
+ 0, /* not writable */
+ NULL, /* no invoker */
+ },
+ {
+ "loginShell", /* name */
+ "s", /* type */
+ SBUS_PROPERTY_READABLE,
+ offsetof(struct iface_ifp_users_user, get_loginShell),
+ sbus_invoke_get_s,
+ 0, /* not writable */
+ NULL, /* no invoker */
+ },
+ {
+ "groups", /* name */
+ "ao", /* type */
+ SBUS_PROPERTY_READABLE,
+ offsetof(struct iface_ifp_users_user, get_groups),
+ sbus_invoke_get_ao,
+ 0, /* not writable */
+ NULL, /* no invoker */
+ },
+ {
+ "extraAttributes", /* name */
+ "a{sas}", /* type */
+ SBUS_PROPERTY_READABLE,
+ offsetof(struct iface_ifp_users_user, get_extraAttributes),
+ sbus_invoke_get_aDOsasDE,
+ 0, /* not writable */
+ NULL, /* no invoker */
+ },
+ { NULL, }
+};
+
+/* interface info for org.freedesktop.sssd.infopipe.Users.User */
+const struct sbus_interface_meta iface_ifp_users_user_meta = {
+ "org.freedesktop.sssd.infopipe.Users.User", /* name */
+ iface_ifp_users_user__methods,
+ NULL, /* no signals */
+ iface_ifp_users_user__properties,
+ sbus_invoke_get_all, /* GetAll invoker */
+};
+
/* invokes a handler with a 'ssu' DBus signature */
static int invoke_ssu_method(struct sbus_request *dbus_req, void *function_ptr)
{
diff --git a/src/responder/ifp/ifp_iface_generated.h b/src/responder/ifp/ifp_iface_generated.h
index 83ac75b06..609bd40e6 100644
--- a/src/responder/ifp/ifp_iface_generated.h
+++ b/src/responder/ifp/ifp_iface_generated.h
@@ -61,6 +61,18 @@
#define IFACE_IFP_USERS_LISTBYNAME "ListByName"
#define IFACE_IFP_USERS_LISTBYDOMAINANDNAME "ListByDomainAndName"
+/* constants for org.freedesktop.sssd.infopipe.Users.User */
+#define IFACE_IFP_USERS_USER "org.freedesktop.sssd.infopipe.Users.User"
+#define IFACE_IFP_USERS_USER_UPDATEGROUPSLIST "UpdateGroupsList"
+#define IFACE_IFP_USERS_USER_NAME "name"
+#define IFACE_IFP_USERS_USER_UIDNUMBER "uidNumber"
+#define IFACE_IFP_USERS_USER_GIDNUMBER "gidNumber"
+#define IFACE_IFP_USERS_USER_GECOS "gecos"
+#define IFACE_IFP_USERS_USER_HOMEDIRECTORY "homeDirectory"
+#define IFACE_IFP_USERS_USER_LOGINSHELL "loginShell"
+#define IFACE_IFP_USERS_USER_GROUPS "groups"
+#define IFACE_IFP_USERS_USER_EXTRAATTRIBUTES "extraAttributes"
+
/* ------------------------------------------------------------------------
* DBus handlers
*
@@ -129,11 +141,11 @@ struct iface_ifp_components {
int (*Disable)(struct sbus_request *req, void *data);
int (*ChangeDebugLevel)(struct sbus_request *req, void *data, uint32_t arg_new_level);
int (*ChangeDebugLevelTemporarily)(struct sbus_request *req, void *data, uint32_t arg_new_level);
- void (*get_name)(struct sbus_request *, void *data, const char * *);
- void (*get_debug_level)(struct sbus_request *, void *data, uint32_t *);
- void (*get_enabled)(struct sbus_request *, void *data, bool *);
- void (*get_type)(struct sbus_request *, void *data, const char * *);
- void (*get_providers)(struct sbus_request *, void *data, const char * * *, int *);
+ void (*get_name)(struct sbus_request *, void *data, const char **);
+ void (*get_debug_level)(struct sbus_request *, void *data, uint32_t*);
+ void (*get_enabled)(struct sbus_request *, void *data, bool*);
+ void (*get_type)(struct sbus_request *, void *data, const char **);
+ void (*get_providers)(struct sbus_request *, void *data, const char ***, int *);
};
/* finish function for Enable */
@@ -151,20 +163,20 @@ int iface_ifp_components_ChangeDebugLevelTemporarily_finish(struct sbus_request
/* vtable for org.freedesktop.sssd.infopipe.Domains */
struct iface_ifp_domains {
struct sbus_vtable vtable; /* derive from sbus_vtable */
- void (*get_name)(struct sbus_request *, void *data, const char * *);
- void (*get_provider)(struct sbus_request *, void *data, const char * *);
- void (*get_primary_servers)(struct sbus_request *, void *data, const char * * *, int *);
- void (*get_backup_servers)(struct sbus_request *, void *data, const char * * *, int *);
- void (*get_min_id)(struct sbus_request *, void *data, uint32_t *);
- void (*get_max_id)(struct sbus_request *, void *data, uint32_t *);
- void (*get_realm)(struct sbus_request *, void *data, const char * *);
- void (*get_forest)(struct sbus_request *, void *data, const char * *);
- void (*get_login_format)(struct sbus_request *, void *data, const char * *);
- void (*get_fully_qualified_name_format)(struct sbus_request *, void *data, const char * *);
- void (*get_enumerable)(struct sbus_request *, void *data, bool *);
- void (*get_use_fully_qualified_names)(struct sbus_request *, void *data, bool *);
- void (*get_subdomain)(struct sbus_request *, void *data, bool *);
- void (*get_parent_domain)(struct sbus_request *, void *data, const char * *);
+ void (*get_name)(struct sbus_request *, void *data, const char **);
+ void (*get_provider)(struct sbus_request *, void *data, const char **);
+ void (*get_primary_servers)(struct sbus_request *, void *data, const char ***, int *);
+ void (*get_backup_servers)(struct sbus_request *, void *data, const char ***, int *);
+ void (*get_min_id)(struct sbus_request *, void *data, uint32_t*);
+ void (*get_max_id)(struct sbus_request *, void *data, uint32_t*);
+ void (*get_realm)(struct sbus_request *, void *data, const char **);
+ void (*get_forest)(struct sbus_request *, void *data, const char **);
+ void (*get_login_format)(struct sbus_request *, void *data, const char **);
+ void (*get_fully_qualified_name_format)(struct sbus_request *, void *data, const char **);
+ void (*get_enumerable)(struct sbus_request *, void *data, bool*);
+ void (*get_use_fully_qualified_names)(struct sbus_request *, void *data, bool*);
+ void (*get_subdomain)(struct sbus_request *, void *data, bool*);
+ void (*get_parent_domain)(struct sbus_request *, void *data, const char **);
};
/* vtable for org.freedesktop.sssd.infopipe.Users */
@@ -188,6 +200,23 @@ int iface_ifp_users_ListByName_finish(struct sbus_request *req, const char *arg_
/* finish function for ListByDomainAndName */
int iface_ifp_users_ListByDomainAndName_finish(struct sbus_request *req, const char *arg_result[], int len_result);
+/* vtable for org.freedesktop.sssd.infopipe.Users.User */
+struct iface_ifp_users_user {
+ struct sbus_vtable vtable; /* derive from sbus_vtable */
+ int (*UpdateGroupsList)(struct sbus_request *req, void *data);
+ void (*get_name)(struct sbus_request *, void *data, const char **);
+ void (*get_uidNumber)(struct sbus_request *, void *data, uint32_t*);
+ void (*get_gidNumber)(struct sbus_request *, void *data, uint32_t*);
+ void (*get_gecos)(struct sbus_request *, void *data, const char **);
+ void (*get_homeDirectory)(struct sbus_request *, void *data, const char **);
+ void (*get_loginShell)(struct sbus_request *, void *data, const char **);
+ void (*get_groups)(struct sbus_request *, void *data, const char ***, int *);
+ void (*get_extraAttributes)(struct sbus_request *, void *data, hash_table_t **);
+};
+
+/* finish function for UpdateGroupsList */
+int iface_ifp_users_user_UpdateGroupsList_finish(struct sbus_request *req);
+
/* ------------------------------------------------------------------------
* DBus Interface Metadata
*
@@ -210,4 +239,7 @@ extern const struct sbus_interface_meta iface_ifp_domains_meta;
/* interface info for org.freedesktop.sssd.infopipe.Users */
extern const struct sbus_interface_meta iface_ifp_users_meta;
+/* interface info for org.freedesktop.sssd.infopipe.Users.User */
+extern const struct sbus_interface_meta iface_ifp_users_user_meta;
+
#endif /* __IFP_IFACE_XML__ */
diff --git a/src/responder/ifp/ifp_private.h b/src/responder/ifp/ifp_private.h
index f76655fa1..94c9a4b85 100644
--- a/src/responder/ifp/ifp_private.h
+++ b/src/responder/ifp/ifp_private.h
@@ -73,9 +73,13 @@ int ifp_req_create_handle_failure(struct sbus_request *dbus_req, errno_t err);
errno_t ifp_add_ldb_el_to_dict(DBusMessageIter *iter_dict,
struct ldb_message_element *el);
-const char **ifp_parse_attr_list(TALLOC_CTX *mem_ctx, const char *conf_str);
const char **
-ifp_parse_attr_list_ex(TALLOC_CTX *mem_ctx, const char *conf_str,
- const char **defaults);
+ifp_parse_user_attr_list(TALLOC_CTX *mem_ctx, const char *conf_str);
+
+const char **
+ifp_get_user_extra_attributes(TALLOC_CTX *mem_ctx, struct ifp_ctx *ifp_ctx);
+
bool ifp_attr_allowed(const char *whitelist[], const char *attr);
+bool ifp_is_user_attr_allowed(struct ifp_ctx *ifp_ctx, const char *attr);
+
#endif /* _IFPSRV_PRIVATE_H_ */
diff --git a/src/responder/ifp/ifp_users.c b/src/responder/ifp/ifp_users.c
index 04fabf77b..26c1aa696 100644
--- a/src/responder/ifp/ifp_users.c
+++ b/src/responder/ifp/ifp_users.c
@@ -24,10 +24,12 @@
#include "db/sysdb.h"
#include "util/util.h"
+#include "util/strtonum.h"
#include "sbus/sssd_dbus_errors.h"
#include "responder/common/responder.h"
#include "responder/common/responder_cache_req.h"
#include "responder/ifp/ifp_users.h"
+#include "responder/ifp/ifp_groups.h"
char * ifp_users_build_path_from_msg(TALLOC_CTX *mem_ctx,
struct sss_domain_info *domain,
@@ -44,6 +46,41 @@ char * ifp_users_build_path_from_msg(TALLOC_CTX *mem_ctx,
return sbus_opath_compose(mem_ctx, IFP_PATH_USERS, domain->name, uid);
}
+static errno_t ifp_users_decompose_path(struct sss_domain_info *domains,
+ const char *path,
+ struct sss_domain_info **_domain,
+ uid_t *_uid)
+{
+ char **parts = NULL;
+ struct sss_domain_info *domain;
+ uid_t uid;
+ errno_t ret;
+
+ ret = sbus_opath_decompose_exact(NULL, path, IFP_PATH_USERS, 2, &parts);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ domain = find_domain_by_name(domains, parts[0], false);
+ if (domain == NULL) {
+ ret = ERR_DOMAIN_NOT_FOUND;
+ goto done;
+ }
+
+ uid = strtouint32(parts[1], NULL, 10);
+ if (errno != 0) {
+ ret = errno;
+ goto done;
+ }
+
+ *_domain = domain;
+ *_uid = uid;
+
+done:
+ talloc_free(parts);
+ return ret;
+}
+
static void ifp_users_find_by_name_done(struct tevent_req *req);
int ifp_users_find_by_name(struct sbus_request *sbus_req,
@@ -200,3 +237,425 @@ int ifp_users_list_by_domain_and_name(struct sbus_request *sbus_req,
{
return EOK;
}
+
+static errno_t
+ifp_users_user_get(struct sbus_request *sbus_req,
+ struct ifp_ctx *ifp_ctx,
+ uid_t *_uid,
+ struct sss_domain_info **_domain,
+ struct ldb_message **_user)
+{
+ struct sss_domain_info *domain;
+ struct ldb_result *res;
+ uid_t uid;
+ errno_t ret;
+
+ ret = ifp_users_decompose_path(ifp_ctx->rctx->domains, sbus_req->path,
+ &domain, &uid);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to decompose object path"
+ "[%s] [%d]: %s\n", sbus_req->path, ret, sss_strerror(ret));
+ return ret;
+ }
+
+ if (_user != NULL) {
+ ret = sysdb_getpwuid_with_views(sbus_req, domain, uid, &res);
+ if (ret == EOK && res->count == 0) {
+ *_user = NULL;
+ ret = ENOENT;
+ }
+
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to lookup user %u@%s [%d]: %s\n",
+ uid, domain->name, ret, sss_strerror(ret));
+ } else {
+ *_user = res->msgs[0];
+ }
+ }
+
+ if (ret == EOK || ret == ENOENT) {
+ if (_uid != NULL) {
+ *_uid = uid;
+ }
+
+ if (_domain != NULL) {
+ *_domain = domain;
+ }
+ }
+
+ return ret;
+}
+
+static void ifp_users_get_as_string(struct sbus_request *sbus_req,
+ void *data,
+ const char *attr,
+ const char **_out)
+{
+ struct ifp_ctx *ifp_ctx;
+ struct ldb_message *msg;
+ struct sss_domain_info *domain;
+ errno_t ret;
+
+ *_out = NULL;
+
+ ifp_ctx = talloc_get_type(data, struct ifp_ctx);
+ if (ifp_ctx == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n");
+ return;
+ }
+
+ if (!ifp_is_user_attr_allowed(ifp_ctx, attr)) {
+ DEBUG(SSSDBG_TRACE_ALL, "Attribute %s is not allowed\n", attr);
+ return;
+ }
+
+ ret = ifp_users_user_get(sbus_req, ifp_ctx, NULL, &domain, &msg);
+ if (ret != EOK) {
+ return;
+ }
+
+ *_out = sss_view_ldb_msg_find_attr_as_string(domain, msg, attr, NULL);
+
+ return;
+}
+
+static void ifp_users_get_as_uint32(struct sbus_request *sbus_req,
+ void *data,
+ const char *attr,
+ uint32_t *_out)
+{
+ struct ifp_ctx *ifp_ctx;
+ struct ldb_message *msg;
+ struct sss_domain_info *domain;
+ errno_t ret;
+
+ *_out = 0;
+
+ ifp_ctx = talloc_get_type(data, struct ifp_ctx);
+ if (ifp_ctx == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n");
+ return;
+ }
+
+ if (!ifp_is_user_attr_allowed(ifp_ctx, attr)) {
+ DEBUG(SSSDBG_TRACE_ALL, "Attribute %s is not allowed\n", attr);
+ return;
+ }
+
+ ret = ifp_users_user_get(sbus_req, ifp_ctx, NULL, &domain, &msg);
+ if (ret != EOK) {
+ return;
+ }
+
+ *_out = sss_view_ldb_msg_find_attr_as_uint64(domain, msg, attr, 0);
+
+ return;
+}
+
+static void ifp_users_user_update_groups_list_done(struct tevent_req *req);
+
+int ifp_users_user_update_groups_list(struct sbus_request *sbus_req,
+ void *data)
+{
+ struct tevent_req *req;
+ struct ifp_ctx *ctx;
+ struct sss_domain_info *domain;
+ const char *username;
+ struct ldb_message *user;
+ errno_t ret;
+
+ ctx = talloc_get_type(data, struct ifp_ctx);
+ if (ctx == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n");
+ return ERR_INTERNAL;
+ }
+
+ ret = ifp_users_user_get(sbus_req, data, NULL, &domain, &user);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ username = ldb_msg_find_attr_as_string(user, SYSDB_NAME, NULL);
+ if (username == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "User name is empty!\n");
+ return ERR_INTERNAL;
+ }
+
+ req = cache_req_initgr_by_name_send(sbus_req, ctx->rctx->ev, ctx->rctx,
+ ctx->ncache, ctx->neg_timeout, 0,
+ domain->name, username);
+ if (req == NULL) {
+ return ENOMEM;
+ }
+
+ tevent_req_set_callback(req, ifp_users_user_update_groups_list_done,
+ sbus_req);
+
+ return EOK;
+}
+
+static void ifp_users_user_update_groups_list_done(struct tevent_req *req)
+{
+ DBusError *error;
+ struct sbus_request *sbus_req;
+ errno_t ret;
+
+ sbus_req = tevent_req_callback_data(req, struct sbus_request);
+
+ ret = cache_req_initgr_by_name_recv(sbus_req, req, NULL, NULL, NULL);
+ talloc_zfree(req);
+ if (ret == ENOENT) {
+ error = sbus_error_new(sbus_req, SBUS_ERROR_NOT_FOUND,
+ "User not found");
+ goto done;
+ } else if (ret != EOK) {
+ error = sbus_error_new(sbus_req, DBUS_ERROR_FAILED, "Failed to fetch "
+ "user [%d]: %s\n", ret, sss_strerror(ret));
+ goto done;
+ }
+
+done:
+ if (ret != EOK) {
+ sbus_request_fail_and_finish(sbus_req, error);
+ return;
+ }
+
+ iface_ifp_users_user_UpdateGroupsList_finish(sbus_req);
+ return;
+}
+
+void ifp_users_user_get_name(struct sbus_request *sbus_req,
+ void *data,
+ const char **_out)
+{
+ ifp_users_get_as_string(sbus_req, data, SYSDB_NAME, _out);
+}
+
+void ifp_users_user_get_uid_number(struct sbus_request *sbus_req,
+ void *data,
+ uint32_t *_out)
+{
+ ifp_users_get_as_uint32(sbus_req, data, SYSDB_UIDNUM, _out);
+}
+
+void ifp_users_user_get_gid_number(struct sbus_request *sbus_req,
+ void *data,
+ uint32_t *_out)
+{
+ ifp_users_get_as_uint32(sbus_req, data, SYSDB_GIDNUM, _out);
+}
+
+void ifp_users_user_get_gecos(struct sbus_request *sbus_req,
+ void *data,
+ const char **_out)
+{
+ ifp_users_get_as_string(sbus_req, data, SYSDB_GECOS, _out);
+}
+
+void ifp_users_user_get_home_directory(struct sbus_request *sbus_req,
+ void *data,
+ const char **_out)
+{
+ ifp_users_get_as_string(sbus_req, data, SYSDB_HOMEDIR, _out);
+}
+
+void ifp_users_user_get_login_shell(struct sbus_request *sbus_req,
+ void *data,
+ const char **_out)
+{
+ ifp_users_get_as_string(sbus_req, data, SYSDB_SHELL, _out);
+}
+
+void ifp_users_user_get_groups(struct sbus_request *sbus_req,
+ void *data,
+ const char ***_out,
+ int *_size)
+{
+ struct ifp_ctx *ifp_ctx;
+ struct sss_domain_info *domain;
+ const char *username;
+ struct ldb_message *user;
+ struct ldb_result *res;
+ const char **out;
+ int num_groups;
+ gid_t gid;
+ errno_t ret;
+ int i;
+
+ *_out = NULL;
+ *_size = 0;
+
+ ifp_ctx = talloc_get_type(data, struct ifp_ctx);
+ if (ifp_ctx == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n");
+ return;
+ }
+
+ if (!ifp_is_user_attr_allowed(ifp_ctx, "groups")) {
+ DEBUG(SSSDBG_TRACE_ALL, "Attribute %s is not allowed\n",
+ SYSDB_MEMBEROF);
+ return;
+ }
+
+ ret = ifp_users_user_get(sbus_req, ifp_ctx, NULL, &domain, &user);
+ if (ret != EOK) {
+ return;
+ }
+
+ username = ldb_msg_find_attr_as_string(user, SYSDB_NAME, NULL);
+ if (username == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "User name is empty!\n");
+ return;
+ }
+
+ /* Run initgroups. */
+ ret = sysdb_initgroups_with_views(sbus_req, domain, username, &res);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get groups for %s@%s [%d]: %s\n",
+ username, domain->name, ret, sss_strerror(ret));
+ return;
+ }
+
+ if (res->count == 0) {
+ return;
+ }
+
+ out = talloc_zero_array(sbus_req, const char *, res->count);
+ if (out == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero_array() failed\n");
+ return;
+ }
+
+ num_groups = 0;
+ for (i = 0; i < res->count; i++) {
+ gid = sss_view_ldb_msg_find_attr_as_uint64(domain, res->msgs[i],
+ SYSDB_GIDNUM, 0);
+ if (gid == 0) {
+ continue;
+ }
+
+ out[i] = ifp_groups_build_path_from_msg(out, domain, res->msgs[i]);
+ if (out[i] == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "ifp_groups_build_path() failed\n");
+ return;
+ }
+
+ num_groups++;
+ }
+
+ *_out = out;
+ *_size = num_groups;
+}
+
+void ifp_users_user_get_extra_attributes(struct sbus_request *sbus_req,
+ void *data,
+ hash_table_t **_out)
+{
+ struct ifp_ctx *ifp_ctx;
+ struct sss_domain_info *domain;
+ struct ldb_message **user;
+ struct ldb_message_element *el;
+ struct ldb_dn *basedn;
+ size_t count;
+ uid_t uid;
+ const char *filter;
+ const char **extra;
+ hash_table_t *table;
+ hash_key_t key;
+ hash_value_t value;
+ const char **values;
+ errno_t ret;
+ int hret;
+ int i;
+
+ *_out = NULL;
+
+ ifp_ctx = talloc_get_type(data, struct ifp_ctx);
+ if (ifp_ctx == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Invalid pointer!\n");
+ return;
+ }
+
+ extra = ifp_get_user_extra_attributes(sbus_req, ifp_ctx);
+ if (extra == NULL || extra[0] == NULL) {
+ DEBUG(SSSDBG_TRACE_ALL, "No extra attributes to return\n");
+ return;
+ }
+
+ ret = ifp_users_user_get(sbus_req, data, &uid, &domain, NULL);
+ if (ret != EOK) {
+ return;
+ }
+
+ basedn = sysdb_user_base_dn(sbus_req, domain);
+ if (basedn == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "sysdb_user_base_dn() failed\n");
+ return;
+ }
+
+ filter = talloc_asprintf(sbus_req, "(&(%s=%s)(%s=%u))",
+ SYSDB_OBJECTCLASS, SYSDB_USER_CLASS,
+ SYSDB_UIDNUM, uid);
+ if (filter == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_asprintf() failed\n");
+ return;
+ }
+
+ ret = sysdb_search_entry(sbus_req, domain->sysdb, basedn,
+ LDB_SCOPE_ONELEVEL, filter,
+ extra, &count, &user);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to lookup user [%d]: %s\n",
+ ret, sss_strerror(ret));
+ return;
+ }
+
+ if (count == 0) {
+ DEBUG(SSSDBG_TRACE_FUNC, "User %u not found!\n", uid);
+ return;
+ } else if (count > 1) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "More than one entry found!\n");
+ return;
+ }
+
+ ret = sss_hash_create(sbus_req, 10, &table);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create hash table!\n");
+ return;
+ }
+
+ /* Read each extra attribute. */
+ for (i = 0; extra[i] != NULL; i++) {
+ el = ldb_msg_find_element(user[0], extra[i]);
+ if (el == NULL) {
+ DEBUG(SSSDBG_TRACE_ALL, "Attribute %s not found, skipping...\n",
+ extra[i]);
+ continue;
+ }
+
+ values = sss_ldb_el_to_string_list(table, el);
+ if (values == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "sss_ldb_el_to_string_list() failed\n");
+ return;
+ }
+
+ key.type = HASH_KEY_STRING;
+ key.str = talloc_strdup(table, extra[i]);
+ if (key.str == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup() failed\n");
+ return;
+ }
+
+ value.type = HASH_VALUE_PTR;
+ value.ptr = values;
+
+ hret = hash_enter(table, &key, &value);
+ if (hret != HASH_SUCCESS) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Unable to insert entry "
+ "into hash table: %d\n", hret);
+ return;
+ }
+ }
+
+ *_out = table;
+}
diff --git a/src/responder/ifp/ifp_users.h b/src/responder/ifp/ifp_users.h
index a0a079f48..7027ef14e 100644
--- a/src/responder/ifp/ifp_users.h
+++ b/src/responder/ifp/ifp_users.h
@@ -54,4 +54,42 @@ int ifp_users_list_by_domain_and_name(struct sbus_request *sbus_req,
const char *filter,
uint32_t limit);
+/* org.freedesktop.sssd.infopipe.Users.User */
+
+int ifp_users_user_update_groups_list(struct sbus_request *req,
+ void *data);
+
+void ifp_users_user_get_name(struct sbus_request *sbus_req,
+ void *data,
+ const char **_out);
+
+void ifp_users_user_get_uid_number(struct sbus_request *sbus_req,
+ void *data,
+ uint32_t *_out);
+
+void ifp_users_user_get_gid_number(struct sbus_request *sbus_req,
+ void *data,
+ uint32_t *_out);
+
+void ifp_users_user_get_gecos(struct sbus_request *sbus_req,
+ void *data,
+ const char **_out);
+
+void ifp_users_user_get_home_directory(struct sbus_request *sbus_req,
+ void *data,
+ const char **_out);
+
+void ifp_users_user_get_login_shell(struct sbus_request *sbus_req,
+ void *data,
+ const char **_out);
+
+void ifp_users_user_get_groups(struct sbus_request *sbus_req,
+ void *data,
+ const char ***_out,
+ int *_size);
+
+void ifp_users_user_get_extra_attributes(struct sbus_request *sbus_req,
+ void *data,
+ hash_table_t **_out);
+
#endif /* IFP_USERS_H_ */
diff --git a/src/responder/ifp/ifpsrv.c b/src/responder/ifp/ifpsrv.c
index 3f5444186..f804ea197 100644
--- a/src/responder/ifp/ifpsrv.c
+++ b/src/responder/ifp/ifpsrv.c
@@ -300,7 +300,7 @@ int ifp_process_init(TALLOC_CTX *mem_ctx,
goto fail;
}
- ifp_ctx->user_whitelist = ifp_parse_attr_list(ifp_ctx, attr_list_str);
+ ifp_ctx->user_whitelist = ifp_parse_user_attr_list(ifp_ctx, attr_list_str);
talloc_free(attr_list_str);
if (ifp_ctx->user_whitelist == NULL) {
DEBUG(SSSDBG_FATAL_FAILURE,
diff --git a/src/responder/ifp/ifpsrv_util.c b/src/responder/ifp/ifpsrv_util.c
index b6a0b168b..674165ee4 100644
--- a/src/responder/ifp/ifpsrv_util.c
+++ b/src/responder/ifp/ifpsrv_util.c
@@ -24,10 +24,11 @@
#include "db/sysdb.h"
#include "responder/ifp/ifp_private.h"
-#define IFP_DEFAULT_ATTRS {SYSDB_NAME, SYSDB_UIDNUM, \
- SYSDB_GIDNUM, SYSDB_GECOS, \
- SYSDB_HOMEDIR, SYSDB_SHELL, \
- NULL}
+#define IFP_USER_DEFAULT_ATTRS {SYSDB_NAME, SYSDB_UIDNUM, \
+ SYSDB_GIDNUM, SYSDB_GECOS, \
+ SYSDB_HOMEDIR, SYSDB_SHELL, \
+ "groups", \
+ NULL}
errno_t ifp_req_create(struct sbus_request *dbus_req,
struct ifp_ctx *ifp_ctx,
@@ -175,13 +176,6 @@ errno_t ifp_add_ldb_el_to_dict(DBusMessageIter *iter_dict,
return EOK;
}
-const char **
-ifp_parse_attr_list(TALLOC_CTX *mem_ctx, const char *conf_str)
-{
- const char *defaults[] = IFP_DEFAULT_ATTRS;
-
- return parse_attr_list_ex(mem_ctx, conf_str, defaults);
-}
bool
ifp_attr_allowed(const char *whitelist[], const char *attr)
@@ -200,3 +194,78 @@ ifp_attr_allowed(const char *whitelist[], const char *attr)
return (whitelist[i]) ? true : false;
}
+
+const char **
+ifp_parse_user_attr_list(TALLOC_CTX *mem_ctx, const char *csv)
+{
+ static const char *defaults[] = IFP_USER_DEFAULT_ATTRS;
+
+ return parse_attr_list_ex(mem_ctx, csv, defaults);
+}
+
+const char **
+ifp_get_user_extra_attributes(TALLOC_CTX *mem_ctx, struct ifp_ctx *ifp_ctx)
+{
+ TALLOC_CTX *tmp_ctx = NULL;
+ const char *std[] = IFP_USER_DEFAULT_ATTRS;
+ const char **whitelist = ifp_ctx->user_whitelist;
+ const char **extra;
+ bool found;
+ int extra_num;
+ int i, j;
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
+ return NULL;
+ }
+
+ for (i = 0; whitelist[i] != NULL; i++) {
+ /* Just count number of attributes in whitelist. */
+ }
+
+ extra = talloc_zero_array(tmp_ctx, const char *, i + 1);
+ if (extra == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero_array() failed\n");
+ goto fail;
+ }
+
+ extra_num = 0;
+ for (i = 0; whitelist[i] != NULL; i++) {
+ found = false;
+ for (j = 0; std[j] != NULL; j++) {
+ if (strcmp(whitelist[i], std[j]) == 0) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ extra[extra_num] = talloc_strdup(extra, whitelist[i]);
+ if (extra[extra_num] == NULL) {
+ goto fail;
+ }
+
+ extra_num++;
+ }
+ }
+
+ extra = talloc_realloc(tmp_ctx, extra, const char *, extra_num + 1);
+ if (extra == NULL) {
+ goto fail;
+ }
+
+ talloc_steal(mem_ctx, extra);
+ talloc_free(tmp_ctx);
+ return extra;
+
+fail:
+ talloc_free(tmp_ctx);
+ return NULL;
+}
+
+bool
+ifp_is_user_attr_allowed(struct ifp_ctx *ifp_ctx, const char *attr)
+{
+ return ifp_attr_allowed(ifp_ctx->user_whitelist, attr);
+}
diff --git a/src/responder/ifp/org.freedesktop.sssd.infopipe.conf b/src/responder/ifp/org.freedesktop.sssd.infopipe.conf
index 195e73aa9..79160bbcc 100644
--- a/src/responder/ifp/org.freedesktop.sssd.infopipe.conf
+++ b/src/responder/ifp/org.freedesktop.sssd.infopipe.conf
@@ -31,6 +31,7 @@
<allow send_interface="org.freedesktop.sssd.infopipe"/>
<allow send_interface="org.freedesktop.sssd.infopipe.Users"/>
+ <allow send_interface="org.freedesktop.sssd.infopipe.Users.User"/>
</policy>
<policy user="root">