summaryrefslogtreecommitdiffstats
path: root/src/responder/nss/nss_protocol_sid.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/responder/nss/nss_protocol_sid.c')
-rw-r--r--src/responder/nss/nss_protocol_sid.c704
1 files changed, 704 insertions, 0 deletions
diff --git a/src/responder/nss/nss_protocol_sid.c b/src/responder/nss/nss_protocol_sid.c
new file mode 100644
index 0000000..69d61bb
--- /dev/null
+++ b/src/responder/nss/nss_protocol_sid.c
@@ -0,0 +1,704 @@
+/*
+ Authors:
+ Pavel Březina <pbrezina@redhat.com>
+
+ Copyright (C) 2016 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 "util/crypto/sss_crypto.h"
+#include "responder/nss/nss_protocol.h"
+
+static errno_t
+find_sss_id_type(struct ldb_message *msg,
+ bool mpg,
+ enum sss_id_type *id_type)
+{
+ size_t c;
+ struct ldb_message_element *el;
+ struct ldb_val *val = NULL;
+
+ el = ldb_msg_find_element(msg, SYSDB_OBJECTCATEGORY);
+ if (el == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "Objectcategory attribute not found.\n");
+ return EINVAL;
+ }
+
+ for (c = 0; c < el->num_values; c++) {
+ val = &(el->values[c]);
+ if (strncasecmp(SYSDB_USER_CLASS,
+ (char *)val->data, val->length) == 0) {
+ break;
+ }
+ }
+
+ if (c == el->num_values) {
+ *id_type = SSS_ID_TYPE_GID;
+ } else {
+ if (mpg) {
+ *id_type = SSS_ID_TYPE_BOTH;
+ } else {
+ *id_type = SSS_ID_TYPE_UID;
+ }
+ }
+
+ return EOK;
+}
+
+static errno_t
+sss_nss_get_id_type(struct sss_nss_cmd_ctx *cmd_ctx,
+ struct cache_req_result *result,
+ enum sss_id_type *_type)
+{
+ errno_t ret;
+ bool mpg;
+
+ /* Well known objects are always groups. */
+ if (result->well_known_object) {
+ *_type = SSS_ID_TYPE_GID;
+ return EOK;
+ }
+
+ mpg = sss_domain_is_mpg(result->domain) || sss_domain_is_hybrid(result->domain);
+ ret = find_sss_id_type(result->msgs[0], mpg, _type);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Unable to find ID type [%d]: %s\n", ret, sss_strerror(ret));
+ return ret;
+ }
+
+ return EOK;
+}
+
+static errno_t
+sss_nss_get_sid_id_type(struct sss_nss_cmd_ctx *cmd_ctx,
+ struct cache_req_result *result,
+ const char **_sid,
+ uint64_t *_id,
+ enum sss_id_type *_type)
+{
+ errno_t ret;
+ size_t c;
+ const char *tmp;
+ const char *user_sid = NULL;
+ const char *group_sid = NULL;
+ uint64_t user_uid = 0;
+ uint64_t user_gid = 0;
+ uint64_t group_gid = 0;
+ enum sss_id_type ltype;
+
+ if (result->count == 1) {
+ *_sid = ldb_msg_find_attr_as_string(result->msgs[0],
+ SYSDB_SID_STR, NULL);
+ if (*_sid == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Missing SID.\n");
+ return EINVAL;
+ }
+ ret = sss_nss_get_id_type(cmd_ctx, result, _type);
+ if (ret == EOK ) {
+ if (*_type == SSS_ID_TYPE_GID) {
+ *_id = ldb_msg_find_attr_as_uint64(result->msgs[0],
+ SYSDB_GIDNUM, 0);
+ } else {
+ *_id = ldb_msg_find_attr_as_uint64(result->msgs[0],
+ SYSDB_UIDNUM, 0);
+ }
+ }
+ return ret;
+ }
+
+ for (c = 0; c < result->count; c++) {
+ ret = find_sss_id_type(result->msgs[c],
+ false /* we are only interested in the type
+ * of the object, so mpg setting can
+ * be ignored */,
+ &ltype);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Unable to find ID type, ignored [%d][%s].\n",
+ ret, sss_strerror(ret));
+ continue;
+ }
+
+ tmp = ldb_msg_find_attr_as_string(result->msgs[c],
+ SYSDB_SID_STR, NULL);
+ if (tmp == NULL) {
+ continue;
+ }
+
+ if (ltype == SSS_ID_TYPE_GID) {
+ if (tmp != NULL && group_sid != NULL) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Search for SID found multiple groups with SIDs: %s, %s;"
+ " request failed.\n", tmp, group_sid);
+ return EINVAL;
+ }
+ group_sid = tmp;
+ group_gid = ldb_msg_find_attr_as_uint64(result->msgs[c],
+ SYSDB_GIDNUM, 0);
+ } else {
+ if (tmp != NULL && user_sid != NULL) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Search for SID found multiple users with SIDs: %s, %s; "
+ "request failed.\n", tmp, user_sid);
+ return EINVAL;
+ }
+ user_sid = tmp;
+ user_uid = ldb_msg_find_attr_as_uint64(result->msgs[c],
+ SYSDB_UIDNUM, 0);
+ user_gid = ldb_msg_find_attr_as_uint64(result->msgs[c],
+ SYSDB_GIDNUM, 0);
+ }
+ }
+
+ if (user_sid == NULL && group_sid == NULL) {
+ /* No SID in the results */
+ return ENOENT;
+ } else if (user_sid != NULL && group_sid == NULL) {
+ /* There is only one user with a SID in the results */
+ *_sid = user_sid;
+ *_id = user_uid;
+ *_type = SSS_ID_TYPE_UID;
+ } else if (user_sid == NULL && group_sid != NULL) {
+ /* There is only one group with a SID in the results */
+ *_sid = group_sid;
+ *_id = group_gid;
+ *_type = SSS_ID_TYPE_GID;
+ } else if (user_sid != NULL && group_sid != NULL && user_uid != 0
+ && user_uid == user_gid && user_gid == group_gid) {
+ /* Manually created user-private-group */
+ *_sid = user_sid;
+ *_id = user_uid;
+ *_type = SSS_ID_TYPE_UID;
+ } else {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Found user with SID [%s] and group with SID [%s] during a "
+ "single request, cannot handle this case.\n",
+ user_sid, group_sid);
+ /* Unrelated user and group both with SIDs are returned, we cannot
+ * handle this case. */
+ return EINVAL;
+ }
+
+ return EOK;
+}
+
+errno_t
+sss_nss_protocol_fill_sid(struct sss_nss_ctx *nss_ctx,
+ struct sss_nss_cmd_ctx *cmd_ctx,
+ struct sss_packet *packet,
+ struct cache_req_result *result)
+{
+ struct sized_string sz_sid;
+ enum sss_id_type id_type;
+ const char *sid;
+ uint64_t id;
+ size_t rp = 0;
+ size_t body_len;
+ uint8_t *body;
+ errno_t ret;
+
+ ret = sss_nss_get_sid_id_type(cmd_ctx, result, &sid, &id, &id_type);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ to_sized_string(&sz_sid, sid);
+
+ ret = sss_packet_grow(packet, sz_sid.len + 3 * sizeof(uint32_t));
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "sss_packet_grow failed.\n");
+ return ret;
+ }
+
+ sss_packet_get_body(packet, &body, &body_len);
+
+ SAFEALIGN_SET_UINT32(&body[rp], 1, &rp); /* Num results. */
+ SAFEALIGN_SET_UINT32(&body[rp], 0, &rp); /* Reserved. */
+ SAFEALIGN_SET_UINT32(&body[rp], id_type, &rp);
+ SAFEALIGN_SET_STRING(&body[rp], sz_sid.str, sz_sid.len, &rp);
+
+ if (nss_ctx->sid_mc_ctx != NULL) {
+ /* no need to check for SSS_NSS_EX_FLAG_INVALIDATE_CACHE since
+ * SID related requests don't support 'flags'
+ */
+ if (id == 0 || id >= UINT32_MAX) {
+ DEBUG(SSSDBG_OP_FAILURE, "Invalid POSIX ID %lu\n", id);
+ return EOK;
+ }
+ ret = sss_mmap_cache_sid_store(&nss_ctx->sid_mc_ctx, &sz_sid,
+ (uint32_t)id, id_type,
+ cmd_ctx->type != CACHE_REQ_OBJECT_BY_ID);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Failed to store SID='%s' / ID=%lu in mmap cache [%d]: %s!\n",
+ sz_sid.str, id, ret, sss_strerror(ret));
+ }
+ }
+
+ return EOK;
+}
+
+static errno_t process_attr_list(TALLOC_CTX *mem_ctx, struct ldb_message *msg,
+ const char **attr_list,
+ struct sized_string **_keys,
+ struct sized_string **_vals,
+ size_t *array_size, size_t *sum,
+ size_t *found)
+{
+ size_t c;
+ size_t d;
+ struct sized_string *keys;
+ struct sized_string *vals;
+ struct ldb_val val;
+ struct ldb_message_element *el;
+ bool use_base64;
+
+ keys = *_keys;
+ vals = *_vals;
+
+ for (c = 0; attr_list[c] != NULL; c++) {
+ el = ldb_msg_find_element(msg, attr_list[c]);
+ if (el != NULL && el->num_values > 0) {
+ if (el->num_values > 1) {
+ *array_size += el->num_values;
+ keys = talloc_realloc(mem_ctx, keys, struct sized_string,
+ *array_size);
+ vals = talloc_realloc(mem_ctx, vals, struct sized_string,
+ *array_size);
+ if (keys == NULL || vals == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n");
+ return ENOMEM;
+ }
+ }
+
+ use_base64 = false;
+ if (strcmp(attr_list[c], SYSDB_USER_CERT) == 0) {
+ use_base64 = true;
+ }
+
+ for (d = 0; d < el->num_values; d++) {
+ to_sized_string(&keys[*found], attr_list[c]);
+ *sum += keys[*found].len;
+ if (use_base64) {
+ val.data = (uint8_t *)sss_base64_encode(vals,
+ el->values[d].data,
+ el->values[d].length);
+ if (val.data != NULL) {
+ val.length = strlen((char *)val.data);
+ }
+ } else {
+ val = el->values[d];
+ }
+
+ if (val.data == NULL || val.data[val.length] != '\0') {
+ DEBUG(SSSDBG_CRIT_FAILURE,
+ "Unexpected attribute value found for [%s].\n",
+ attr_list[c]);
+ return EINVAL;
+ }
+ to_sized_string(&vals[*found], (const char *)val.data);
+ *sum += vals[*found].len;
+
+ (*found)++;
+ }
+ }
+ }
+
+ *_keys = keys;
+ *_vals = vals;
+
+ return EOK;
+}
+
+errno_t
+sss_nss_protocol_fill_orig(struct sss_nss_ctx *nss_ctx,
+ struct sss_nss_cmd_ctx *cmd_ctx,
+ struct sss_packet *packet,
+ struct cache_req_result *result)
+{
+ TALLOC_CTX *tmp_ctx;
+ struct ldb_message *msg = result->msgs[0];
+ const char **full_attrs = NULL;
+ enum sss_id_type id_type;
+ struct sized_string *keys;
+ struct sized_string *vals;
+ size_t full_attrs_count = 0;
+ size_t array_size;
+ size_t sum;
+ size_t found;
+ size_t i;
+ size_t rp = 0;
+ size_t body_len;
+ uint8_t *body;
+ errno_t ret;
+
+ if (result->count != 1) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Unexpected number of results [%u], expected [1].\n",
+ result->count);
+ return EINVAL;
+ }
+
+ tmp_ctx = talloc_new(NULL);
+ if (tmp_ctx == NULL) {
+ return ENOMEM;
+ }
+
+ ret = sss_nss_get_id_type(cmd_ctx, result, &id_type);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ if (nss_ctx->full_attribute_list != NULL) {
+ full_attrs = nss_ctx->full_attribute_list;
+ for (full_attrs_count = 0;
+ full_attrs[full_attrs_count] != NULL;
+ full_attrs_count++);
+ }
+
+ array_size = full_attrs_count;
+ keys = talloc_array(tmp_ctx, struct sized_string, array_size);
+ vals = talloc_array(tmp_ctx, struct sized_string, array_size);
+ if (keys == NULL || vals == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n");
+ ret = ENOMEM;
+ goto done;
+ }
+
+ sum = 0;
+ found = 0;
+
+ if (full_attrs_count != 0) {
+ ret = process_attr_list(tmp_ctx, msg, full_attrs, &keys, &vals,
+ &array_size, &sum, &found);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "process_attr_list failed.\n");
+ goto done;
+ }
+ }
+
+ ret = sss_packet_grow(packet, sum + 3 * sizeof(uint32_t));
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "sss_packet_grow failed.\n");
+ goto done;
+ }
+
+ sss_packet_get_body(packet, &body, &body_len);
+ SAFEALIGN_SETMEM_UINT32(&body[rp], 1, &rp); /* Num results */
+ SAFEALIGN_SETMEM_UINT32(&body[rp], 0, &rp); /* reserved */
+ SAFEALIGN_COPY_UINT32(&body[rp], &id_type, &rp);
+ for (i = 0; i < found; i++) {
+ SAFEALIGN_SET_STRING(&body[rp], keys[i].str, keys[i].len, &rp);
+ SAFEALIGN_SET_STRING(&body[rp], vals[i].str, vals[i].len, &rp);
+ }
+
+ ret = EOK;
+
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+static errno_t
+sss_nss_get_well_known_name(TALLOC_CTX *mem_ctx,
+ struct resp_ctx *rctx,
+ struct cache_req_result *result,
+ struct sized_string **_sz_name)
+{
+ struct sized_string *sz_name;
+ const char *fq_name = NULL;
+ const char *domname;
+ const char *name;
+
+ name = result->lookup_name;
+ if (name == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Missing name.\n");
+ return EINVAL;
+ }
+
+ sz_name = talloc_zero(mem_ctx, struct sized_string);
+ if (sz_name == NULL) {
+ return ENOMEM;
+ }
+
+ domname = result->domain != NULL
+ ? result->domain->name
+ : result->well_known_domain;
+
+ if (domname != NULL) {
+ fq_name = sss_tc_fqname2(sz_name, rctx->global_names,
+ domname, domname, name);
+ if (fq_name == NULL) {
+ DEBUG(SSSDBG_OP_FAILURE, "Conversion to fqname failed.\n");
+ talloc_free(sz_name);
+ return ENOMEM;
+ }
+
+ name = fq_name;
+ }
+
+ to_sized_string(sz_name, name);
+
+ *_sz_name = sz_name;
+
+ return EOK;
+}
+
+static errno_t
+sss_nss_get_ad_name(TALLOC_CTX *mem_ctx,
+ struct resp_ctx *rctx,
+ struct cache_req_result *result,
+ struct sized_string **_sz_name)
+{
+ struct ldb_message *msg = result->msgs[0];
+ const char *name;
+ errno_t ret;
+
+ if (result->well_known_object) {
+ return sss_nss_get_well_known_name(mem_ctx, rctx, result, _sz_name);
+ }
+
+ name = ldb_msg_find_attr_as_string(msg, ORIGINALAD_PREFIX SYSDB_NAME,
+ NULL);
+ if (name == NULL) {
+ name = ldb_msg_find_attr_as_string(msg, SYSDB_NAME, NULL);
+ }
+
+ if (name == NULL) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Missing name.\n");
+ return EINVAL;
+ }
+
+ ret = sized_output_name(mem_ctx, rctx, name, result->domain, _sz_name);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Unable to create sized name [%d]: %s\n",
+ ret, sss_strerror(ret));
+ return ret;
+ }
+
+ return EOK;
+}
+
+errno_t
+sss_nss_protocol_fill_single_name(struct sss_nss_ctx *nss_ctx,
+ struct sss_nss_cmd_ctx *cmd_ctx,
+ struct sss_packet *packet,
+ struct cache_req_result *result)
+{
+ if (result->ldb_result->count > 1) {
+ DEBUG(SSSDBG_TRACE_FUNC, "Lookup returned more than one result "
+ "but only one was expected.\n");
+ return EEXIST;
+ }
+
+ return sss_nss_protocol_fill_name(nss_ctx, cmd_ctx, packet, result);
+}
+
+errno_t
+sss_nss_protocol_fill_name(struct sss_nss_ctx *nss_ctx,
+ struct sss_nss_cmd_ctx *cmd_ctx,
+ struct sss_packet *packet,
+ struct cache_req_result *result)
+{
+ struct sized_string *sz_name;
+ enum sss_id_type id_type;
+ size_t rp = 0;
+ size_t body_len;
+ uint8_t *body;
+ errno_t ret;
+
+ ret = sss_nss_get_id_type(cmd_ctx, result, &id_type);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ ret = sss_nss_get_ad_name(cmd_ctx, nss_ctx->rctx, result, &sz_name);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ ret = sss_packet_grow(packet, sz_name->len + 3 * sizeof(uint32_t));
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "sss_packet_grow failed.\n");
+ talloc_free(sz_name);
+ return ret;
+ }
+
+ sss_packet_get_body(packet, &body, &body_len);
+
+ SAFEALIGN_SET_UINT32(&body[rp], 1, &rp); /* Num results. */
+ SAFEALIGN_SET_UINT32(&body[rp], 0, &rp); /* Reserved. */
+ SAFEALIGN_SET_UINT32(&body[rp], id_type, &rp);
+ SAFEALIGN_SET_STRING(&body[rp], sz_name->str, sz_name->len, &rp);
+
+ talloc_free(sz_name);
+
+ return EOK;
+}
+
+errno_t
+sss_nss_protocol_fill_id(struct sss_nss_ctx *nss_ctx,
+ struct sss_nss_cmd_ctx *cmd_ctx,
+ struct sss_packet *packet,
+ struct cache_req_result *result)
+{
+ struct ldb_message *msg = result->msgs[0];
+ enum sss_id_type id_type;
+ uint64_t id64;
+ uint32_t id;
+ const char *sid = NULL;
+ struct sized_string sid_key;
+ size_t rp = 0;
+ size_t body_len;
+ uint8_t *body;
+ errno_t ret;
+
+ if (result->ldb_result == NULL) {
+ /* This was a well known SID. This is currently unsupported with id. */
+ return EINVAL;
+ }
+
+ ret = sss_nss_get_id_type(cmd_ctx, result, &id_type);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ if (id_type == SSS_ID_TYPE_GID) {
+ id64 = ldb_msg_find_attr_as_uint64(msg, SYSDB_GIDNUM, 0);
+ } else {
+ id64 = ldb_msg_find_attr_as_uint64(msg, SYSDB_UIDNUM, 0);
+ }
+
+ if (id64 == 0 || id64 >= UINT32_MAX) {
+ DEBUG(SSSDBG_CRIT_FAILURE, "Invalid POSIX ID.\n");
+ return EINVAL;
+ }
+
+ id = (uint32_t)id64;
+
+ ret = sss_packet_grow(packet, 4 * sizeof(uint32_t));
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "sss_packet_grow failed.\n");
+ return ret;
+ }
+
+ sss_packet_get_body(packet, &body, &body_len);
+
+ SAFEALIGN_SET_UINT32(&body[rp], 1, &rp); /* Num results. */
+ SAFEALIGN_SET_UINT32(&body[rp], 0, &rp); /* Reserved. */
+ SAFEALIGN_SET_UINT32(&body[rp], id_type, &rp);
+ SAFEALIGN_SET_UINT32(&body[rp], id, &rp);
+
+ if (nss_ctx->sid_mc_ctx != NULL) {
+ /* no need to check for SSS_NSS_EX_FLAG_INVALIDATE_CACHE since
+ * SID related requests don't support 'flags'
+ */
+ sid = ldb_msg_find_attr_as_string(msg, SYSDB_SID_STR, NULL);
+ if (!sid) {
+ DEBUG(SSSDBG_OP_FAILURE, "Missing SID?!\n");
+ return EOK;
+ }
+ to_sized_string(&sid_key, sid);
+ ret = sss_mmap_cache_sid_store(&nss_ctx->sid_mc_ctx, &sid_key, id, id_type,
+ cmd_ctx->type != CACHE_REQ_OBJECT_BY_ID);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE,
+ "Failed to store SID='%s' / ID=%d in mmap cache [%d]: %s!\n",
+ sid, id, ret, sss_strerror(ret));
+ }
+ }
+
+ return EOK;
+}
+
+errno_t
+sss_nss_protocol_fill_name_list_all_domains(struct sss_nss_ctx *nss_ctx,
+ struct sss_nss_cmd_ctx *cmd_ctx,
+ struct sss_packet *packet,
+ struct cache_req_result **results)
+{
+ enum sss_id_type *id_types;
+ size_t rp = 0;
+ size_t body_len;
+ uint8_t *body;
+ errno_t ret;
+ struct sized_string *sz_names;
+ size_t len;
+ size_t c;
+ const char *tmp_str;
+ size_t d;
+ size_t total = 0;
+ size_t iter = 0;
+
+ if (results == NULL) {
+ return EINVAL;
+ }
+
+ for (d = 0; results[d] != NULL; d++) {
+ total += results[d]->count;
+ }
+
+ sz_names = talloc_array(cmd_ctx, struct sized_string, total);
+ if (sz_names == NULL) {
+ return ENOMEM;
+ }
+
+ id_types = talloc_array(cmd_ctx, enum sss_id_type, total);
+ if (id_types == NULL) {
+ return ENOMEM;
+ }
+
+ len = 0;
+ for (d = 0; results[d] != NULL; d++) {
+ for (c = 0; c < results[d]->count; c++) {
+ ret = sss_nss_get_id_type(cmd_ctx, results[d], &(id_types[iter]));
+ if (ret != EOK) {
+ return ret;
+ }
+
+ tmp_str = sss_get_name_from_msg(results[d]->domain,
+ results[d]->msgs[c]);
+ if (tmp_str == NULL) {
+ return EINVAL;
+ }
+ to_sized_string(&(sz_names[iter]), tmp_str);
+
+ len += sz_names[iter].len;
+ iter++;
+ }
+ }
+
+ len += (2 + total) * sizeof(uint32_t);
+
+ ret = sss_packet_grow(packet, len);
+ if (ret != EOK) {
+ DEBUG(SSSDBG_OP_FAILURE, "sss_packet_grow failed.\n");
+ return ret;
+ }
+
+ sss_packet_get_body(packet, &body, &body_len);
+
+ SAFEALIGN_SET_UINT32(&body[rp], total, &rp); /* Num results. */
+ SAFEALIGN_SET_UINT32(&body[rp], 0, &rp); /* Reserved. */
+ for (c = 0; c < total; c++) {
+ SAFEALIGN_SET_UINT32(&body[rp], id_types[c], &rp);
+ SAFEALIGN_SET_STRING(&body[rp], sz_names[c].str, sz_names[c].len,
+ &rp);
+ }
+
+ return EOK;
+}