summaryrefslogtreecommitdiffstats
path: root/server/infopipe/infopipe_users.c
diff options
context:
space:
mode:
authorStephen Gallagher <sgallagh@redhat.com>2009-03-02 09:35:06 -0500
committerSimo Sorce <ssorce@redhat.com>2009-03-02 09:47:54 -0500
commit5e3966c99180abdcd1e21774a882f1c14c47aae8 (patch)
tree1a882b9d49f2c7ac25d70f0bbb644b5cefed6439 /server/infopipe/infopipe_users.c
parent6f5b1ad8c234d58041e45aef4558d50f44d7f021 (diff)
downloadsssd-5e3966c99180abdcd1e21774a882f1c14c47aae8.tar.gz
sssd-5e3966c99180abdcd1e21774a882f1c14c47aae8.tar.xz
sssd-5e3966c99180abdcd1e21774a882f1c14c47aae8.zip
Implement GetUserAttributes in the InfoPipe
This patch adds support for requesting user data in the sysdb via the InfoPipe. It currently has support for reading defined entries of integral, floating-point or string types. Tasks remaining: 1) Implement call to the provider when cache is out of date 2) Support byte arrays for userpic and similar I modified sysdb_search_ctx in sysdb_search.c to accept an array of attributes to pass into the LDB search. I also made one additional related fix: the btreemap now sorts in the correct order. Previously I had accidentally transposed the two values for sorting, so the map would always have been in exact reverse order.
Diffstat (limited to 'server/infopipe/infopipe_users.c')
-rw-r--r--server/infopipe/infopipe_users.c666
1 files changed, 660 insertions, 6 deletions
diff --git a/server/infopipe/infopipe_users.c b/server/infopipe/infopipe_users.c
index 2c107bc47..82889fa86 100644
--- a/server/infopipe/infopipe_users.c
+++ b/server/infopipe/infopipe_users.c
@@ -19,8 +19,17 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <dbus/dbus.h>
+#include <ldb.h>
+#include <time.h>
#include "util/util.h"
-#include "infopipe.h"
+#include "util/btreemap.h"
+#include "confdb/confdb.h"
+#include "infopipe/infopipe.h"
+#include "infopipe/infopipe_private.h"
+#include "infopipe/sysbus.h"
+#include "db/sysdb.h"
+
+static int attr_comparator(const void *key1, const void *key2);
int infp_users_get_cached(DBusMessage *message, struct sbus_conn_ctx *sconn)
{
@@ -61,19 +70,664 @@ int infp_users_delete(DBusMessage *message, struct sbus_conn_ctx *sconn)
return EOK;
}
-int infp_users_get_attr(DBusMessage *message, struct sbus_conn_ctx *sconn)
+struct infp_getattr_ctx {
+ char *caller;
+ struct sss_domain_info *domain;
+ struct infp_req_ctx *infp_req;
+ char **usernames;
+ uint32_t username_count;
+ char **attributes;
+ uint32_t attr_count;
+ uint32_t index;
+ bool check_provider;
+
+ /* The results array must have username_count elements */
+ struct btreemap **results;
+};
+
+static int infp_get_attr_lookup(struct infp_getattr_ctx *infp_getattr_req);
+
+struct infp_attr_variant {
+ int dbus_type;
+ int subtype;
+ int count;
+ void *data;
+};
+
+/* We are restricting variants to three basic types:
+ * Fixed (Numeric) types
+ * Strings
+ * Arrays of fixed (numeric) types
+ */
+static int infp_user_getattr_append_dict(TALLOC_CTX *mem_ctx,
+ DBusMessageIter *iter,
+ struct btreemap *map)
+{
+ int ret, i;
+ char **attrs;
+ struct infp_attr_variant *value;
+ char *vartype;
+ char *subtype;
+ int attr_count;
+ DBusMessageIter array_iter;
+ DBusMessageIter dict_iter;
+ DBusMessageIter variant_iter;
+ dbus_bool_t dbret;
+
+ ret = btreemap_get_keys(mem_ctx, map, (const void ***)&attrs, &attr_count);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ /* DICTs are an array of dict pairs */
+ dbret = dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "{sv}", &array_iter);
+ if (!dbret) {
+ ret = ENOMEM;
+ goto error;
+ }
+
+ i = 0;
+ while (i < attr_count) {
+ if (strcasecmp(attrs[i], SYSDB_LAST_UPDATE) == 0) {
+ /* Skip lastUpdate. We shouldn't be returning this */
+ i++;
+ continue;
+ }
+
+ /* Create the variant value */
+ value = talloc_get_type(btreemap_get_value(map, attrs[i]), struct infp_attr_variant);
+ if (value == NULL) {
+ /* Skip any entries that returned an empty value */
+ i++;
+ continue;
+ }
+
+ /* Open a dict container for this pair */
+ dbret = dbus_message_iter_open_container(&array_iter, DBUS_TYPE_DICT_ENTRY, NULL, &dict_iter);
+ if (!dbret) {
+ ret = ENOMEM;
+ goto error;
+ }
+ /* Write the dict key */
+ dbret = dbus_message_iter_append_basic(&dict_iter, DBUS_TYPE_STRING, &attrs[i]);
+ if (!dbret) {
+ ret = ENOMEM;
+ goto error;
+ }
+
+ vartype = NULL;
+ subtype = NULL;
+ if (sbus_is_dbus_string_type(value->dbus_type)) {
+ /* String types are strings, object paths and signatures */
+ vartype = talloc_asprintf(mem_ctx, "%c", value->dbus_type);
+ if (vartype == NULL) {
+ ret = ENOMEM;
+ goto error;
+ }
+ dbret = dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_VARIANT, vartype, &variant_iter);
+ if (!dbret) {
+ ret = ENOMEM;
+ goto error;
+ }
+ dbret = dbus_message_iter_append_basic(&variant_iter, DBUS_TYPE_STRING, &value->data);
+ if (!dbret) {
+ ret = ENOMEM;
+ goto error;
+ }
+ talloc_free(vartype);
+ vartype = NULL;
+ }
+
+ else if (sbus_is_dbus_fixed_type(value->dbus_type)) {
+ /* Fixed types are booleans, bytes, the integral types and the floating-point types */
+ vartype = talloc_asprintf(mem_ctx, "%c", value->dbus_type);
+ if (vartype == NULL) {
+ ret = ENOMEM;
+ goto error;
+ }
+ dbret = dbus_message_iter_open_container(&dict_iter, DBUS_TYPE_VARIANT, vartype, &variant_iter);
+ if (!dbret) {
+ ret = ENOMEM;
+ goto error;
+ }
+ dbret = dbus_message_iter_append_basic(&variant_iter, value->dbus_type, value->data);
+ if (!dbret) {
+ ret = ENOMEM;
+ goto error;
+ }
+ talloc_free(vartype);
+ vartype = NULL;
+ }
+ /* FIXME: Need to support byte arrays for userpic and similar */
+
+ else {
+ /* Value type not yet supported */
+ DEBUG(0, ("Attempted to create DICT value for something not a basic type or fixed array [%d]\n", value->dbus_type));
+ ret = EINVAL;
+ goto error;
+ }
+
+ /* Close the variant */
+ dbret = dbus_message_iter_close_container(&dict_iter, &variant_iter);
+ if(!dbret) {
+ ret = ENOMEM;
+ goto error;
+ }
+
+ /* Close the dict */
+ dbret = dbus_message_iter_close_container(&array_iter, &dict_iter);
+ if(!dbret) {
+ ret = ENOMEM;
+ goto error;
+ }
+ i++;
+ }
+
+ /* Close the dict array */
+ dbret = dbus_message_iter_close_container(iter, &array_iter);
+ if(!dbret) {
+ ret = ENOMEM;
+ goto error;
+ }
+
+ return EOK;
+
+error:
+ talloc_free(attrs);
+ talloc_free(vartype);
+ talloc_free(subtype);
+ return ret;
+}
+
+static int create_getattr_result_map(TALLOC_CTX *mem_ctx, struct infp_getattr_ctx *infp_getattr_req,
+ struct ldb_result *res, struct btreemap **results)
+{
+ int i, ret;
+ int attr_type, subtype;
+ struct infp_attr_variant *variant;
+ const char *tmp_string;
+
+ /* Iterate through the requested attributes */
+ for (i=0; i < infp_getattr_req->attr_count; i++) {
+ /* Ignore any attributes we don't care about */
+ attr_type = infp_get_attribute_type(infp_getattr_req->attributes[i]);
+ if (attr_type != INFP_ATTR_TYPE_INVALID) {
+ variant = talloc_zero(mem_ctx, struct infp_attr_variant);
+ if (variant == NULL) {
+ ret = ENOMEM;
+ goto end;
+ }
+ variant->dbus_type = infp_get_user_attr_dbus_type(attr_type, &subtype);
+ switch (variant->dbus_type) {
+ case DBUS_TYPE_STRING:
+ tmp_string = ldb_msg_find_attr_as_string(res->msgs[0], infp_getattr_req->attributes[i], NULL);
+ if (tmp_string == NULL) {
+ /* Attribute was not found in the result list */
+ talloc_free(variant);
+ continue;
+ }
+ variant->data = (void *)talloc_strdup(variant, tmp_string);
+ if (variant->data == NULL) {
+ talloc_free(variant);
+ continue;
+ }
+ break;
+
+ case DBUS_TYPE_BOOLEAN:
+ case DBUS_TYPE_BYTE:
+ case DBUS_TYPE_INT16:
+ case DBUS_TYPE_UINT16:
+ case DBUS_TYPE_INT32:
+ case DBUS_TYPE_UINT32:
+ case DBUS_TYPE_INT64:
+ case DBUS_TYPE_UINT64:
+ /* We'll treat all integral types as UINT64 internally
+ * These will be correctly converted to their true types
+ * when being marshalled on the wire.
+ */
+ variant->data = (void *)talloc(variant, uint64_t);
+ if (variant->data == NULL) {
+ talloc_free(variant);
+ continue;
+ }
+
+ *(uint64_t *)variant->data = ldb_msg_find_attr_as_uint64(res->msgs[0], infp_getattr_req->attributes[i], 0);
+ break;
+
+ default:
+ talloc_free(variant);
+ continue;
+ }
+
+ /* Add the variant to the map */
+ ret = btreemap_set_value(mem_ctx, results, (const void *)infp_getattr_req->attributes[i], variant, attr_comparator);
+ if (ret != EOK) {
+ talloc_free(variant);
+ continue;
+ }
+ }
+ }
+
+ ret = EOK;
+
+end:
+ return ret;
+}
+
+static void infp_get_attr_lookup_callback(void *ptr, int ldb_status, struct ldb_result *res)
{
+ int ret;
+ int i;
+ bool call_provider = false;
+ int timeout;
+ uint64_t lastUpdate;
DBusMessage *reply;
+ DBusMessageIter iter;
+ DBusMessageIter array_iter;
+ struct infp_getattr_ctx *infp_getattr_req = talloc_get_type(ptr, struct infp_getattr_ctx);
- reply = dbus_message_new_error(message, DBUS_ERROR_NOT_SUPPORTED, "Not yet implemented");
+ DEBUG(9, ("Processing results for user [%s]\n", infp_getattr_req->usernames[infp_getattr_req->index]));
- /* send reply */
- sbus_conn_send_reply(sconn, reply);
+ /* Process the current results */
+ if (ldb_status != LDB_SUCCESS) {
+ DEBUG(0, ("Critical error reading from sysdb.\n"));
+ goto done;
+ }
+
+ if(infp_getattr_req->check_provider) {
+ switch(res->count) {
+ case 0:
+ call_provider = true;
+ break;
+
+ case 1:
+ timeout = infp_getattr_req->infp_req->infp->cache_timeout;
+ lastUpdate = ldb_msg_find_attr_as_uint64(res->msgs[0],
+ SYSDB_LAST_UPDATE, 0);
+ if (lastUpdate + timeout < time(NULL)) {
+ call_provider = true;
+ }
+ break;
+
+ default:
+ DEBUG(0, ("GetUser call returned more than one result. This probably means the sysdb is corrupt!\n"));
+ goto done;
+ }
+ }
+
+ if (call_provider) {
+ /* FIXME call the provider */
+ }
+
+ switch (res->count) {
+ case 0:
+ DEBUG(2, ("No results for GetUser"));
+ infp_getattr_req->results[infp_getattr_req->index] = NULL;
+ break;
+
+ case 1:
+ /* Create the result map */
+ ret = create_getattr_result_map(infp_getattr_req, infp_getattr_req, res,
+ &infp_getattr_req->results[infp_getattr_req->index]);
+ if (ret != EOK) {
+ DEBUG(0, ("Unable to create result map!\n"));
+ goto done;
+ }
+ break;
+ default:
+ /* We received more than one result. This is bad */
+ DEBUG(0, ("GetUser call returned more than one result. This probably means the sysdb is corrupt!\n"));
+ goto done;
+ }
+
+ /* If there are more usernames remaining in the list, re-enter the loop */
+ infp_getattr_req->index++;
+ if (infp_getattr_req->index < infp_getattr_req->username_count) {
+ ret = infp_get_attr_lookup(infp_getattr_req);
+ if (ret != EOK) {
+ DEBUG(0, ("Could not read from cache database\n"));
+ goto done;
+ }
+ return;
+ }
+
+ /* No more names remain, return the result DICTs */
+ reply = dbus_message_new_method_return(infp_getattr_req->infp_req->req_message);
+ if (reply == NULL) {
+ goto done;
+ }
+
+ dbus_message_iter_init_append(reply, &iter);
+
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "a{sv}", &array_iter);
+ i = 0;
+ while (i < infp_getattr_req->username_count) {
+ ret = infp_user_getattr_append_dict(infp_getattr_req, &array_iter, infp_getattr_req->results[i]);
+ if (ret != EOK) {
+ DEBUG(0, ("Unable to append response DICT\n"));
+ goto done;
+ }
+ i++;
+ }
+ dbus_message_iter_close_container(&iter, &array_iter);
+
+ sbus_conn_send_reply(infp_getattr_req->infp_req->sconn, reply);
+
+done:
+ talloc_free(infp_getattr_req);
+}
+
+int infp_get_user_attr_dbus_type(int attr_type, int *subtype)
+{
+ int dbus_type;
+
+ switch(attr_type) {
+ case INFP_ATTR_TYPE_DEFAULTGROUP:
+ case INFP_ATTR_TYPE_GECOS:
+ case INFP_ATTR_TYPE_HOMEDIR:
+ case INFP_ATTR_TYPE_SHELL:
+ case INFP_ATTR_TYPE_FULLNAME:
+ case INFP_ATTR_TYPE_LOCALE:
+ case INFP_ATTR_TYPE_KEYBOARD:
+ case INFP_ATTR_TYPE_SESSION:
+ dbus_type = DBUS_TYPE_STRING;
+ break;
+ case INFP_ATTR_TYPE_LAST_LOGIN:
+ dbus_type = DBUS_TYPE_UINT64;
+ break;
+ case INFP_ATTR_TYPE_USERPIC:
+ dbus_type = DBUS_TYPE_ARRAY;
+ *subtype = DBUS_TYPE_BYTE;
+ break;
+ default:
+ dbus_type = DBUS_TYPE_INVALID;
+ }
+ return dbus_type;
+}
+
+static int attr_comparator(const void *key1, const void *key2)
+{
+ return strcmp((const char *)key1, (const char *)key2);
+}
+
+static int infp_get_attr_lookup(struct infp_getattr_ctx *infp_getattr_req)
+{
+ uint32_t i;
+ int ret;
+ char **attributes;
+ const char *last_update;
+ int attr_count;
+
+ DEBUG(9, ("Processing lookup for user [%s]\n", infp_getattr_req->usernames[infp_getattr_req->index]));
+
+ if (infp_getattr_req->index >= infp_getattr_req->username_count) {
+ /* Avoid index bound issues */
+ return EINVAL;
+ }
+
+ /* Check permissions */
+ i=0;
+ infp_getattr_req->results[infp_getattr_req->index] = NULL;
+ while(i < infp_getattr_req->attr_count) {
+ if(infp_get_permissions(infp_getattr_req->caller,
+ infp_getattr_req->domain,
+ INFP_OBJ_TYPE_USER,
+ infp_getattr_req->usernames[infp_getattr_req->index],
+ INFP_ACTION_TYPE_READ,
+ infp_get_attribute_type(infp_getattr_req->attributes[i]))
+ ) {
+ /* Add this attribute as a key to the result map
+ * This will guarantee that we are requesting only unique attributes
+ * that we have permission to read
+ */
+ ret = btreemap_set_value(infp_getattr_req, &infp_getattr_req->results[infp_getattr_req->index],
+ infp_getattr_req->attributes[i], NULL, attr_comparator);
+ if (ret != EOK) {
+ return ret;
+ }
+ }
+ i++;
+ }
+
+ /* Always add SYSDB_LAST_UPDATE to the list, we won't return it */
+ last_update = talloc_strdup(infp_getattr_req, SYSDB_LAST_UPDATE);
+ ret = btreemap_set_value(infp_getattr_req, &infp_getattr_req->results[infp_getattr_req->index],
+ last_update, NULL, attr_comparator);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ /* Prepare the list of attributes to request from the sysdb */
+ attr_count = 0;
+ ret = btreemap_get_keys(infp_getattr_req,
+ infp_getattr_req->results[infp_getattr_req->index],
+ (const void ***)&attributes, &attr_count);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ if (attr_count == 1) {
+ /* There were zero authorized attributes in the list
+ * No need to call sysdb, just move to the next username
+ * The single attribute was SYSDB_LAST_UPDATE which we
+ * added manually.
+ */
+ infp_getattr_req->index++;
+ return infp_get_attr_lookup(infp_getattr_req);
+ }
+
+ /* Add a trailing NULL entry (required for sysdb) */
+ attributes = talloc_realloc(infp_getattr_req, attributes, char *, attr_count+1);
+ if (attributes == NULL) {
+ return ENOMEM;
+ }
+ attributes[attr_count] = NULL;
+
+ /* Call into the sysdb for the requested attributes */
+ ret = sysdb_get_user_attr(infp_getattr_req,
+ infp_getattr_req->infp_req->infp->sysdb,
+ infp_getattr_req->domain,
+ infp_getattr_req->usernames[infp_getattr_req->index],
+ (const char **)attributes,
+ infp_get_attr_lookup_callback, infp_getattr_req);
- dbus_message_unref(reply);
return EOK;
}
+static char **infp_get_all_attributes(TALLOC_CTX *mem_ctx, uint32_t *attr_count)
+{
+ char **attributes;
+ int offset = 0;
+
+ *attr_count = 10;
+ attributes = talloc_array(mem_ctx, char *, *attr_count);
+ if (attributes == NULL) {
+ return NULL;
+ }
+
+ attributes[offset++] = talloc_strdup(attributes, SYSDB_USER_ATTR_DEFAULTGROUP);
+ if(!attributes[offset]) goto error;
+
+ attributes[offset++] = talloc_strdup(attributes, SYSDB_USER_ATTR_GECOS);
+ if(!attributes[offset]) goto error;
+
+ attributes[offset++] = talloc_strdup(attributes, SYSDB_USER_ATTR_HOMEDIR);
+ if(!attributes[offset]) goto error;
+
+ attributes[offset++] = talloc_strdup(attributes, SYSDB_USER_ATTR_SHELL);
+ if(!attributes[offset]) goto error;
+
+ attributes[offset++] = talloc_strdup(attributes, SYSDB_USER_ATTR_FULLNAME);
+ if(!attributes[offset]) goto error;
+
+ attributes[offset++] = talloc_strdup(attributes, SYSDB_USER_ATTR_LOCALE);
+ if(!attributes[offset]) goto error;
+
+ attributes[offset++] = talloc_strdup(attributes, SYSDB_USER_ATTR_KEYBOARD);
+ if(!attributes[offset]) goto error;
+
+ attributes[offset++] = talloc_strdup(attributes, SYSDB_USER_ATTR_SESSION);
+ if(!attributes[offset]) goto error;
+
+ attributes[offset++] = talloc_strdup(attributes, SYSDB_USER_ATTR_LAST_LOGIN);
+ if(!attributes[offset]) goto error;
+
+ attributes[offset++] = talloc_strdup(attributes, SYSDB_USER_ATTR_USERPIC);
+ if(!attributes[offset]) goto error;
+
+ return attributes;
+
+error:
+ talloc_free(attributes);
+ *attr_count = 0;
+ return NULL;
+}
+
+/* GetUserAttributes(ARRAY(STRING) usernames,
+ * STRING domain,
+ * ARRAY(STRING) filter)
+ */
+int infp_users_get_attr(DBusMessage *message, struct sbus_conn_ctx *sconn)
+{
+ int ret, i;
+ DBusMessage *reply;
+ DBusError error;
+ dbus_bool_t dbret;
+ char **usernames;
+ uint32_t username_count;
+ char *domain;
+ char **attributes;
+ uint32_t attr_count;
+ struct infp_getattr_ctx *infp_getattr_req;
+
+ usernames = NULL;
+ attributes = NULL;
+ /* Get the arguments to GetAttributes */
+ dbus_error_init(&error);
+ dbret = dbus_message_get_args(message, &error,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &usernames, &username_count,
+ DBUS_TYPE_STRING, &domain,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &attributes, &attr_count,
+ DBUS_TYPE_INVALID);
+ if(!dbret) {
+ DEBUG(0, ("Parsing arguments failed: %s:%s\n", error.name, error.message));
+ dbus_free_string_array(usernames);
+ dbus_free_string_array(attributes);
+
+ reply = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, error.message);
+ sbus_conn_send_reply(sconn, reply);
+
+ dbus_message_unref(reply);
+ dbus_error_free(&error);
+
+ return EOK;
+ }
+
+ if (username_count < 1) {
+ /* No usernames received. Return an error */
+ reply = dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS, "No usernames specified.");
+ sbus_conn_send_reply(sconn, reply);
+
+ dbus_free_string_array(usernames);
+ dbus_free_string_array(attributes);
+ dbus_message_unref(reply);
+ ret = EOK;
+ }
+
+ /* Create a infp_getattr_ctx */
+ infp_getattr_req = talloc_zero(NULL, struct infp_getattr_ctx);
+ if (infp_getattr_req == NULL) {
+ ret = ENOMEM;
+ goto end;
+ }
+
+ /* Create an infp_req_ctx */
+ infp_getattr_req->infp_req = talloc_zero(infp_getattr_req, struct infp_req_ctx);
+ if (infp_getattr_req == NULL) {
+ ret = ENOMEM;
+ goto end;
+ }
+ infp_getattr_req->infp_req->infp = talloc_get_type(sbus_conn_get_private_data(sconn), struct infp_ctx);
+ infp_getattr_req->infp_req->sconn = sconn;
+ infp_getattr_req->infp_req->req_message = message;
+ infp_getattr_req->domain = btreemap_get_value(infp_getattr_req->infp_req->infp->domain_map, (const void *)domain);
+ infp_getattr_req->check_provider = strcasecmp(domain, "LOCAL");
+
+ /* Copy the username list */
+ infp_getattr_req->usernames = talloc_array(infp_getattr_req, char *, username_count);
+ if (infp_getattr_req->usernames == NULL) {
+ ret = ENOMEM;
+ goto end;
+ }
+
+ i = 0;
+ while (i < username_count) {
+ DEBUG(9, ("Request for user [%s]\n", usernames[i]));
+ infp_getattr_req->usernames[i] = talloc_strdup(infp_getattr_req->usernames, usernames[i]);
+ if (infp_getattr_req == NULL) {
+ ret = ENOMEM;
+ goto end;
+ }
+ i++;
+ }
+ infp_getattr_req->username_count = username_count;
+
+ /* Copy the attribute list */
+ if (attr_count > 0) {
+ infp_getattr_req->attributes = talloc_array(infp_getattr_req, char *, attr_count);
+ if (infp_getattr_req->attributes == NULL) {
+ ret = ENOMEM;
+ goto end;
+ }
+ i = 0;
+ while (i < attr_count) {
+ infp_getattr_req->attributes[i] = talloc_strdup(infp_getattr_req, attributes[i]);
+ if (infp_getattr_req == NULL) {
+ ret = ENOMEM;
+ goto end;
+ }
+ i++;
+ }
+ infp_getattr_req->attr_count = attr_count;
+ } else {
+ /* No attributes specified in the call means retrieve all possible */
+ infp_getattr_req->attributes = infp_get_all_attributes(infp_getattr_req, &infp_getattr_req->attr_count);
+ if (infp_getattr_req->attributes == NULL) {
+ ret = ENOMEM;
+ goto end;
+ }
+ }
+
+ infp_getattr_req->index = 0;
+
+ infp_getattr_req->caller = sysbus_get_caller(infp_getattr_req, message, sconn);
+ if (infp_getattr_req->caller == NULL) {
+ ret = EIO;
+ goto end;
+ }
+
+ /* Prepare the result list */
+ infp_getattr_req->results = talloc_array(infp_getattr_req, struct btreemap *, attr_count);
+ if (infp_getattr_req->results == NULL) {
+ ret = ENOMEM;
+ goto end;
+ }
+
+ /* Look up the first username and start the async loop */
+ ret = infp_get_attr_lookup(infp_getattr_req);
+ if (ret != EOK) {
+ DEBUG(0, ("Could not read from cache database\n"));
+ }
+
+end:
+ dbus_free_string_array(usernames);
+ dbus_free_string_array(attributes);
+ if (ret != EOK) {
+ talloc_free(infp_getattr_req);
+ }
+ return ret;
+}
+
int infp_users_set_attr(DBusMessage *message, struct sbus_conn_ctx *sconn)
{
DBusMessage *reply;