URL: https://github.com/SSSD/sssd/pull/264 Author: sumit-bose Title: #264: sss_nss_getlistbycert: return results from multiple domains Action: synchronized
To pull the PR as Git branch: git remote add ghsssd https://github.com/SSSD/sssd git fetch ghsssd pull/264/head:pr264 git checkout pr264
From 93b28cedd8e3c31f644259772ff4c0bbde4281fa Mon Sep 17 00:00:00 2001 From: Sumit Bose <sb...@redhat.com> Date: Tue, 9 May 2017 16:57:43 +0200 Subject: [PATCH] sss_nss_getlistbycert: return results from multiple domains Currently only the results from one domain were returned although all domains were searched and the results were available. Unit tests are updated to cover this case as well. Resolves https://pagure.io/SSSD/sssd/issue/3393 --- src/responder/nss/nss_cmd.c | 87 +++++++++++++++++++++++++++++++++++- src/responder/nss/nss_protocol.h | 6 +++ src/responder/nss/nss_protocol_sid.c | 78 ++++++++++++++++++++++++++++++++ src/tests/cmocka/test_nss_srv.c | 33 +++++++++----- 4 files changed, 192 insertions(+), 12 deletions(-) diff --git a/src/responder/nss/nss_cmd.c b/src/responder/nss/nss_cmd.c index 1931bf6..a4727c1 100644 --- a/src/responder/nss/nss_cmd.c +++ b/src/responder/nss/nss_cmd.c @@ -51,6 +51,7 @@ nss_cmd_ctx_create(TALLOC_CTX *mem_ctx, } static void nss_getby_done(struct tevent_req *subreq); +static void nss_getlistby_done(struct tevent_req *subreq); static errno_t nss_getby_name(struct cli_ctx *cli_ctx, enum cache_req_type type, @@ -212,6 +213,89 @@ static errno_t nss_getby_svc(struct cli_ctx *cli_ctx, return EOK; } +static errno_t nss_getlistby_cert(struct cli_ctx *cli_ctx, + enum cache_req_type type) +{ + struct nss_cmd_ctx *cmd_ctx; + struct tevent_req *subreq; + const char *cert; + errno_t ret; + + cmd_ctx = nss_cmd_ctx_create(cli_ctx, cli_ctx, type, NULL); + if (cmd_ctx == NULL) { + ret = ENOMEM; + goto done; + } + + cmd_ctx->sid_id_type = SSS_ID_TYPE_UID; + + ret = nss_protocol_parse_cert(cli_ctx, &cert); + if (ret != EOK) { + DEBUG(SSSDBG_CRIT_FAILURE, "Invalid request message!\n"); + goto done; + } + + DEBUG(SSSDBG_TRACE_FUNC, "Input cert: %s\n", get_last_x_chars(cert, 10)); + + subreq = cache_req_user_by_cert_send(cmd_ctx, cli_ctx->ev, cli_ctx->rctx, + cli_ctx->rctx->ncache, 0, + CACHE_REQ_ANY_DOM, NULL, + cert); + if (subreq == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "cache_req_user_by_cert_send failed.\n"); + ret = ENOMEM; + goto done; + } + tevent_req_set_callback(subreq, nss_getlistby_done, cmd_ctx); + + ret = EOK; + +done: + if (ret != EOK) { + talloc_free(cmd_ctx); + return nss_protocol_done(cli_ctx, ret); + } + + return EOK; +} + +static void nss_getlistby_done(struct tevent_req *subreq) +{ + struct cache_req_result **results; + struct nss_cmd_ctx *cmd_ctx; + errno_t ret; + struct cli_protocol *pctx; + + cmd_ctx = tevent_req_callback_data(subreq, struct nss_cmd_ctx); + + ret = cache_req_recv(cmd_ctx, subreq, &results); + talloc_zfree(subreq); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "cache_req_user_by_cert request failed.\n"); + goto done; + } + + pctx = talloc_get_type(cmd_ctx->cli_ctx->protocol_ctx, struct cli_protocol); + + ret = sss_packet_new(pctx->creq, 0, sss_packet_get_cmd(pctx->creq->in), + &pctx->creq->out); + if (ret != EOK) { + goto done; + } + + ret = nss_protocol_fill_name_list_all_domains(cmd_ctx->nss_ctx, cmd_ctx, + pctx->creq->out, results); + if (ret != EOK) { + goto done; + } + + sss_packet_set_error(pctx->creq->out, EOK); + +done: + nss_protocol_done(cmd_ctx->cli_ctx, ret); + talloc_free(cmd_ctx); +} + static errno_t nss_getby_cert(struct cli_ctx *cli_ctx, enum cache_req_type type, nss_protocol_fill_packet_fn fill_fn) @@ -934,8 +1018,7 @@ static errno_t nss_cmd_getnamebycert(struct cli_ctx *cli_ctx) static errno_t nss_cmd_getlistbycert(struct cli_ctx *cli_ctx) { - return nss_getby_cert(cli_ctx, CACHE_REQ_USER_BY_CERT, - nss_protocol_fill_name_list); + return nss_getlistby_cert(cli_ctx, CACHE_REQ_USER_BY_CERT); } struct sss_cmd_table *get_nss_cmds(void) diff --git a/src/responder/nss/nss_protocol.h b/src/responder/nss/nss_protocol.h index e4c0e52..417b089 100644 --- a/src/responder/nss/nss_protocol.h +++ b/src/responder/nss/nss_protocol.h @@ -181,6 +181,12 @@ nss_protocol_fill_name_list(struct nss_ctx *nss_ctx, struct cache_req_result *result); errno_t +nss_protocol_fill_name_list_all_domains(struct nss_ctx *nss_ctx, + struct nss_cmd_ctx *cmd_ctx, + struct sss_packet *packet, + struct cache_req_result **results); + +errno_t nss_protocol_fill_id(struct nss_ctx *nss_ctx, struct nss_cmd_ctx *cmd_ctx, struct sss_packet *packet, diff --git a/src/responder/nss/nss_protocol_sid.c b/src/responder/nss/nss_protocol_sid.c index a6a4e27..858e9f7 100644 --- a/src/responder/nss/nss_protocol_sid.c +++ b/src/responder/nss/nss_protocol_sid.c @@ -561,3 +561,81 @@ nss_protocol_fill_name_list(struct nss_ctx *nss_ctx, return EOK; } + +errno_t +nss_protocol_fill_name_list_all_domains(struct nss_ctx *nss_ctx, + struct 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 = nss_get_id_type(cmd_ctx, results[d], &(id_types[iter])); + if (ret != EOK) { + return ret; + } + + tmp_str = nss_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; +} diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c index 8c72f44..03b5bcc 100644 --- a/src/tests/cmocka/test_nss_srv.c +++ b/src/tests/cmocka/test_nss_srv.c @@ -3808,7 +3808,8 @@ static int test_nss_getnamebycert_check(uint32_t status, uint8_t *body, size_t b return EOK; } -static int test_nss_getlistbycert_check(uint32_t status, uint8_t *body, size_t blen) +static int test_nss_getlistbycert_check_exp(uint32_t status, uint8_t *body, + size_t blen, size_t exp) { size_t rp = 0; uint32_t id_type; @@ -3817,13 +3818,13 @@ static int test_nss_getlistbycert_check(uint32_t status, uint8_t *body, size_t b const char *name; int found = 0; const char *fq_name1 = "testcertuser@"TEST_DOM_NAME ; - const char *fq_name2 = "testcertuser2@"TEST_DOM_NAME; + const char *fq_name2 = "testcertuser2@"TEST_SUBDOM_NAME; assert_int_equal(status, EOK); /* num_results and reserved */ SAFEALIGN_COPY_UINT32(&num, body + rp, &rp); - assert_in_range(num, 1, 2); + assert_int_equal(num, exp); SAFEALIGN_COPY_UINT32(&reserved, body + rp, &rp); assert_int_equal(reserved, 0); @@ -3858,6 +3859,17 @@ static int test_nss_getlistbycert_check(uint32_t status, uint8_t *body, size_t b return EOK; } +static int test_nss_getlistbycert_check_one(uint32_t status, uint8_t *body, + size_t blen) +{ + return test_nss_getlistbycert_check_exp(status, body, blen, 1); +} + +static int test_nss_getlistbycert_check_two(uint32_t status, uint8_t *body, + size_t blen) +{ + return test_nss_getlistbycert_check_exp(status, body, blen, 2); +} static void test_nss_getnamebycert(void **state) { @@ -3949,7 +3961,7 @@ static void test_nss_getlistbycert(void **state) der = sss_base64_decode(nss_test_ctx, TEST_TOKEN_CERT, &der_size); assert_non_null(der); - ret = sysdb_attrs_add_mem(attrs, SYSDB_USER_CERT, der, der_size); + ret = sysdb_attrs_add_mem(attrs, SYSDB_USER_MAPPED_CERT, der, der_size); talloc_free(der); assert_int_equal(ret, EOK); @@ -3967,7 +3979,7 @@ static void test_nss_getlistbycert(void **state) /* Should go straight to back end, without contacting DP. */ /* If there is only a single user mapped the result will look like the */ /* result of getnamebycert. */ - set_cmd_cb(test_nss_getlistbycert_check); + set_cmd_cb(test_nss_getlistbycert_check_one); ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETLISTBYCERT, nss_test_ctx->nss_cmds); assert_int_equal(ret, EOK); @@ -3990,7 +4002,7 @@ static void test_nss_getlistbycert_multi(void **state) attrs = sysdb_new_attrs(nss_test_ctx); assert_non_null(attrs); - ret = sysdb_attrs_add_mem(attrs, SYSDB_USER_CERT, der, der_size); + ret = sysdb_attrs_add_mem(attrs, SYSDB_USER_MAPPED_CERT, der, der_size); assert_int_equal(ret, EOK); /* Prime the cache with two valid user */ @@ -4004,11 +4016,11 @@ static void test_nss_getlistbycert_multi(void **state) attrs = sysdb_new_attrs(nss_test_ctx); assert_non_null(attrs); - ret = sysdb_attrs_add_mem(attrs, SYSDB_USER_CERT, der, der_size); + ret = sysdb_attrs_add_mem(attrs, SYSDB_USER_MAPPED_CERT, der, der_size); talloc_free(der); assert_int_equal(ret, EOK); - ret = store_user(nss_test_ctx, nss_test_ctx->tctx->dom, + ret = store_user(nss_test_ctx, nss_test_ctx->subdom, &testbycert2, attrs, 0); assert_int_equal(ret, EOK); talloc_free(attrs); @@ -4019,7 +4031,7 @@ static void test_nss_getlistbycert_multi(void **state) /* Query for that user, call a callback when command finishes */ /* Should go straight to back end, without contacting DP */ - set_cmd_cb(test_nss_getlistbycert_check); + set_cmd_cb(test_nss_getlistbycert_check_two); ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETLISTBYCERT, nss_test_ctx->nss_cmds); assert_int_equal(ret, EOK); @@ -4290,7 +4302,8 @@ int main(int argc, const char *argv[]) cmocka_unit_test_setup_teardown(test_nss_getlistbycert, nss_test_setup, nss_test_teardown), cmocka_unit_test_setup_teardown(test_nss_getlistbycert_multi, - nss_test_setup, nss_test_teardown), + nss_subdom_test_setup, + nss_subdom_test_teardown), cmocka_unit_test_setup_teardown(test_nss_getsidbyname, nss_test_setup, nss_test_teardown), cmocka_unit_test_setup_teardown(test_nss_getsidbyupn,
_______________________________________________ sssd-devel mailing list -- sssd-devel@lists.fedorahosted.org To unsubscribe send an email to sssd-devel-le...@lists.fedorahosted.org