diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/responder/nss/nsssrv_cmd.c | 88 | ||||
-rw-r--r-- | src/tests/cmocka/test_nss_srv.c | 131 |
2 files changed, 198 insertions, 21 deletions
diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c index 3c5d45071..6bb03d81b 100644 --- a/src/responder/nss/nsssrv_cmd.c +++ b/src/responder/nss/nsssrv_cmd.c @@ -4612,13 +4612,14 @@ static errno_t fill_orig(struct sss_packet *packet, { int ret; TALLOC_CTX *tmp_ctx; - const char *tmp_str; uint8_t *body; size_t blen; size_t pctr = 0; size_t c; + size_t d; size_t sum; size_t found; + size_t array_size; size_t extra_attrs_count = 0; const char **extra_attrs_list = NULL; const char *orig_attr_list[] = {SYSDB_SID_STR, @@ -4637,6 +4638,8 @@ static errno_t fill_orig(struct sss_packet *packet, struct sized_string *keys; struct sized_string *vals; struct nss_ctx *nctx; + struct ldb_message_element *el; + struct ldb_val *val; tmp_ctx = talloc_new(NULL); if (tmp_ctx == NULL) { @@ -4652,10 +4655,9 @@ static errno_t fill_orig(struct sss_packet *packet, extra_attrs_count++); } - keys = talloc_array(tmp_ctx, struct sized_string, - sizeof(orig_attr_list) + extra_attrs_count); - vals = talloc_array(tmp_ctx, struct sized_string, - sizeof(orig_attr_list) + extra_attrs_count); + array_size = sizeof(orig_attr_list) + extra_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; @@ -4665,26 +4667,72 @@ static errno_t fill_orig(struct sss_packet *packet, sum = 0; found = 0; for (c = 0; orig_attr_list[c] != NULL; c++) { - tmp_str = ldb_msg_find_attr_as_string(msg, orig_attr_list[c], NULL); - if (tmp_str != NULL) { - to_sized_string(&keys[found], orig_attr_list[c]); - sum += keys[found].len; - to_sized_string(&vals[found], tmp_str); - sum += vals[found].len; + el = ldb_msg_find_element(msg, orig_attr_list[c]); + if (el != NULL && el->num_values > 0) { + if (el->num_values > 1) { + array_size += el->num_values; + keys = talloc_realloc(tmp_ctx, keys, struct sized_string, + array_size); + vals = talloc_realloc(tmp_ctx, vals, struct sized_string, + array_size); + if (keys == NULL || vals == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n"); + ret = ENOMEM; + goto done; + } + } + for (d = 0; d < el->num_values; d++) { + to_sized_string(&keys[found], orig_attr_list[c]); + sum += keys[found].len; + val = &(el->values[d]); + if (val == NULL || val->data == NULL + || val->data[val->length] != '\0') { + DEBUG(SSSDBG_CRIT_FAILURE, + "Unexpected attribute value found for [%s].\n", + orig_attr_list[c]); + ret = EINVAL; + goto done; + } + to_sized_string(&vals[found], (const char *)val->data); + sum += vals[found].len; - found++; + found++; + } } } for (c = 0; c < extra_attrs_count; c++) { - tmp_str = ldb_msg_find_attr_as_string(msg, extra_attrs_list[c], NULL); - if (tmp_str != NULL) { - to_sized_string(&keys[found], extra_attrs_list[c]); - sum += keys[found].len; - to_sized_string(&vals[found], tmp_str); - sum += vals[found].len; - - found++; + el = ldb_msg_find_element(msg, extra_attrs_list[c]); + if (el != NULL && el->num_values > 0) { + if (el->num_values > 1) { + array_size += el->num_values; + keys = talloc_realloc(tmp_ctx, keys, struct sized_string, + array_size); + vals = talloc_realloc(tmp_ctx, vals, struct sized_string, + array_size); + if (keys == NULL || vals == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n"); + ret = ENOMEM; + goto done; + } + } + for (d = 0; d < el->num_values; d++) { + to_sized_string(&keys[found], extra_attrs_list[c]); + sum += keys[found].len; + val = &(el->values[d]); + if (val == NULL || val->data == NULL + || val->data[val->length] != '\0') { + DEBUG(SSSDBG_CRIT_FAILURE, + "Unexpected attribute value found for [%s].\n", + orig_attr_list[c]); + ret = EINVAL; + goto done; + } + to_sized_string(&vals[found], (const char *)val->data); + sum += vals[found].len; + + found++; + } } } diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c index 8f297a784..7d958dbb3 100644 --- a/src/tests/cmocka/test_nss_srv.c +++ b/src/tests/cmocka/test_nss_srv.c @@ -51,7 +51,8 @@ struct nss_test_ctx { bool ncache_hit; }; -const char *global_extra_attrs[] = {"phone", "mobile", NULL}; +const char *global_extra_attrs[] = {"phone", "mobile", SYSDB_ORIG_MEMBEROF, + NULL}; struct nss_test_ctx *nss_test_ctx; @@ -1945,6 +1946,132 @@ void test_nss_getorigbyname_extra_attrs(void **state) assert_int_equal(ret, EOK); } + +static int test_nss_getorigbyname_multi_check(uint32_t status, uint8_t *body, + size_t blen) +{ + const char *s; + enum sss_id_type id_type; + size_t rp = 2 * sizeof(uint32_t); + + assert_int_equal(status, EOK); + + SAFEALIGN_COPY_UINT32(&id_type, body+rp, &rp); + assert_int_equal(id_type, SSS_ID_TYPE_UID); + + /* Sequence of null terminated strings */ + s = (char *) body+rp; + assert_string_equal(s, SYSDB_SID_STR); + rp += strlen(s) + 1; + assert_true(rp < blen); + + s = (char *) body+rp; + assert_string_equal(s, "S-1-2-3-4"); + rp += strlen(s) + 1; + assert_true(rp < blen); + + s = (char *) body+rp; + assert_string_equal(s, ORIGINALAD_PREFIX SYSDB_NAME); + rp += strlen(s) + 1; + assert_true(rp < blen); + + s = (char *) body+rp; + assert_string_equal(s, "orig_name"); + rp += strlen(s) + 1; + assert_true(rp < blen); + + s = (char *) body+rp; + assert_string_equal(s, ORIGINALAD_PREFIX SYSDB_UIDNUM); + rp += strlen(s) + 1; + assert_true(rp < blen); + + s = (char *) body+rp; + assert_string_equal(s, "1234"); + rp += strlen(s) + 1; + assert_true(rp < blen); + + s = (char *) body+rp; + assert_string_equal(s, SYSDB_ORIG_MEMBEROF); + rp += strlen(s) + 1; + assert_true(rp < blen); + + s = (char *) body+rp; + assert_string_equal(s, "cn=abc"); + rp += strlen(s) + 1; + assert_true(rp < blen); + + s = (char *) body+rp; + assert_string_equal(s, SYSDB_ORIG_MEMBEROF); + rp += strlen(s) + 1; + assert_true(rp < blen); + + s = (char *) body+rp; + assert_string_equal(s, "cn=def"); + rp += strlen(s) + 1; + assert_true(rp < blen); + + s = (char *) body+rp; + assert_string_equal(s, SYSDB_ORIG_MEMBEROF); + rp += strlen(s) + 1; + assert_true(rp < blen); + + s = (char *) body+rp; + assert_string_equal(s, "cn=123"); + rp += strlen(s) + 1; + assert_int_equal(rp, blen); + + return EOK; +} +void test_nss_getorigbyname_multi_value_attrs(void **state) +{ + errno_t ret; + struct sysdb_attrs *attrs; + + attrs = sysdb_new_attrs(nss_test_ctx); + assert_non_null(attrs); + + ret = sysdb_attrs_add_string(attrs, SYSDB_SID_STR, "S-1-2-3-4"); + assert_int_equal(ret, EOK); + + ret = sysdb_attrs_add_string(attrs, ORIGINALAD_PREFIX SYSDB_NAME, + "orig_name"); + assert_int_equal(ret, EOK); + + ret = sysdb_attrs_add_uint32(attrs, ORIGINALAD_PREFIX SYSDB_UIDNUM, 1234); + assert_int_equal(ret, EOK); + + ret = sysdb_attrs_add_string(attrs, SYSDB_ORIG_MEMBEROF, "cn=abc"); + assert_int_equal(ret, EOK); + + ret = sysdb_attrs_add_string(attrs, SYSDB_ORIG_MEMBEROF, "cn=def"); + assert_int_equal(ret, EOK); + + ret = sysdb_attrs_add_string(attrs, SYSDB_ORIG_MEMBEROF, "cn=123"); + assert_int_equal(ret, EOK); + + /* Prime the cache with a valid user */ + ret = sysdb_add_user(nss_test_ctx->tctx->dom, + "testuserorigmulti", 3456, 7890, + "test user orig multi value", + "/home/testuserorigextra", "/bin/sh", NULL, + attrs, 300, 0); + assert_int_equal(ret, EOK); + + mock_input_user_or_group("testuserorigmulti"); + will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETORIGBYNAME); + will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL); + + /* Query for that user, call a callback when command finishes */ + set_cmd_cb(test_nss_getorigbyname_multi_check); + ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETORIGBYNAME, + nss_test_ctx->nss_cmds); + assert_int_equal(ret, EOK); + + /* Wait until the test finishes with EOK */ + ret = test_ev_loop(nss_test_ctx->tctx); + assert_int_equal(ret, EOK); +} + void nss_test_setup(void **state) { struct sss_test_conf_param params[] = { @@ -2095,6 +2222,8 @@ int main(int argc, const char *argv[]) nss_test_setup, nss_test_teardown), unit_test_setup_teardown(test_nss_getorigbyname_extra_attrs, nss_test_setup_extra_attr, nss_test_teardown), + unit_test_setup_teardown(test_nss_getorigbyname_multi_value_attrs, + nss_test_setup_extra_attr, nss_test_teardown), }; /* Set debug level to invalid value so we can deside if -d 0 was used. */ |