diff options
author | Pavel Březina <pbrezina@redhat.com> | 2015-02-09 12:02:33 +0100 |
---|---|---|
committer | Jakub Hrozek <jhrozek@redhat.com> | 2015-05-22 15:57:14 +0200 |
commit | a1e4113a5388e34c08459c5b69679c82ac2bddc9 (patch) | |
tree | de092388bfceb31b3038ce3cfb056cff6f31bf65 /src/responder/ifp/ifp_users.c | |
parent | c747b0c875785ce693f70b50bdda0237c4b04e35 (diff) | |
download | sssd-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/ifp/ifp_users.c')
-rw-r--r-- | src/responder/ifp/ifp_users.c | 459 |
1 files changed, 459 insertions, 0 deletions
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; +} |