Blame SOURCES/0128-sss_nss_getlistbycert-return-results-from-multiple-d.patch

ecf709
From 71731d26dc4f2c36989779f327b0e9a399486e14 Mon Sep 17 00:00:00 2001
ecf709
From: Sumit Bose <sbose@redhat.com>
ecf709
Date: Tue, 9 May 2017 16:57:43 +0200
ecf709
Subject: [PATCH] sss_nss_getlistbycert: return results from multiple domains
ecf709
MIME-Version: 1.0
ecf709
Content-Type: text/plain; charset=UTF-8
ecf709
Content-Transfer-Encoding: 8bit
ecf709
ecf709
Currently only the results from one domain were returned although all
ecf709
domains were searched and the results were available. Unit tests are
ecf709
updated to cover this case as well.
ecf709
ecf709
Resolves https://pagure.io/SSSD/sssd/issue/3393
ecf709
ecf709
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
ecf709
---
ecf709
 src/responder/nss/nss_cmd.c          | 87 +++++++++++++++++++++++++++++++++++-
ecf709
 src/responder/nss/nss_protocol.h     |  6 +++
ecf709
 src/responder/nss/nss_protocol_sid.c | 78 ++++++++++++++++++++++++++++++++
ecf709
 src/tests/cmocka/test_nss_srv.c      | 33 +++++++++-----
ecf709
 4 files changed, 192 insertions(+), 12 deletions(-)
ecf709
ecf709
diff --git a/src/responder/nss/nss_cmd.c b/src/responder/nss/nss_cmd.c
ecf709
index 1931bf62a686c7f30852dac547866609cf54a81b..a4727c18786a86c28b5415ba82295967a47a8ec0 100644
ecf709
--- a/src/responder/nss/nss_cmd.c
ecf709
+++ b/src/responder/nss/nss_cmd.c
ecf709
@@ -51,6 +51,7 @@ nss_cmd_ctx_create(TALLOC_CTX *mem_ctx,
ecf709
 }
ecf709
 
ecf709
 static void nss_getby_done(struct tevent_req *subreq);
ecf709
+static void nss_getlistby_done(struct tevent_req *subreq);
ecf709
 
ecf709
 static errno_t nss_getby_name(struct cli_ctx *cli_ctx,
ecf709
                               enum cache_req_type type,
ecf709
@@ -212,6 +213,89 @@ done:
ecf709
     return EOK;
ecf709
 }
ecf709
 
ecf709
+static errno_t nss_getlistby_cert(struct cli_ctx *cli_ctx,
ecf709
+                                  enum cache_req_type type)
ecf709
+{
ecf709
+    struct nss_cmd_ctx *cmd_ctx;
ecf709
+    struct tevent_req *subreq;
ecf709
+    const char *cert;
ecf709
+    errno_t ret;
ecf709
+
ecf709
+    cmd_ctx = nss_cmd_ctx_create(cli_ctx, cli_ctx, type, NULL);
ecf709
+    if (cmd_ctx == NULL) {
ecf709
+        ret = ENOMEM;
ecf709
+        goto done;
ecf709
+    }
ecf709
+
ecf709
+    cmd_ctx->sid_id_type = SSS_ID_TYPE_UID;
ecf709
+
ecf709
+    ret = nss_protocol_parse_cert(cli_ctx, &cert);
ecf709
+    if (ret != EOK) {
ecf709
+        DEBUG(SSSDBG_CRIT_FAILURE, "Invalid request message!\n");
ecf709
+        goto done;
ecf709
+    }
ecf709
+
ecf709
+    DEBUG(SSSDBG_TRACE_FUNC, "Input cert: %s\n", get_last_x_chars(cert, 10));
ecf709
+
ecf709
+    subreq = cache_req_user_by_cert_send(cmd_ctx, cli_ctx->ev, cli_ctx->rctx,
ecf709
+                                         cli_ctx->rctx->ncache, 0,
ecf709
+                                         CACHE_REQ_ANY_DOM, NULL,
ecf709
+                                         cert);
ecf709
+    if (subreq == NULL) {
ecf709
+        DEBUG(SSSDBG_OP_FAILURE, "cache_req_user_by_cert_send failed.\n");
ecf709
+        ret = ENOMEM;
ecf709
+        goto done;
ecf709
+    }
ecf709
+    tevent_req_set_callback(subreq, nss_getlistby_done, cmd_ctx);
ecf709
+
ecf709
+    ret = EOK;
ecf709
+
ecf709
+done:
ecf709
+    if (ret != EOK) {
ecf709
+        talloc_free(cmd_ctx);
ecf709
+        return nss_protocol_done(cli_ctx, ret);
ecf709
+    }
ecf709
+
ecf709
+    return EOK;
ecf709
+}
ecf709
+
ecf709
+static void nss_getlistby_done(struct tevent_req *subreq)
ecf709
+{
ecf709
+    struct cache_req_result **results;
ecf709
+    struct nss_cmd_ctx *cmd_ctx;
ecf709
+    errno_t ret;
ecf709
+    struct cli_protocol *pctx;
ecf709
+
ecf709
+    cmd_ctx = tevent_req_callback_data(subreq, struct nss_cmd_ctx);
ecf709
+
ecf709
+    ret = cache_req_recv(cmd_ctx, subreq, &results);
ecf709
+    talloc_zfree(subreq);
ecf709
+    if (ret != EOK) {
ecf709
+        DEBUG(SSSDBG_OP_FAILURE, "cache_req_user_by_cert request failed.\n");
ecf709
+        goto done;
ecf709
+    }
ecf709
+
ecf709
+    pctx = talloc_get_type(cmd_ctx->cli_ctx->protocol_ctx, struct cli_protocol);
ecf709
+
ecf709
+    ret = sss_packet_new(pctx->creq, 0, sss_packet_get_cmd(pctx->creq->in),
ecf709
+                         &pctx->creq->out);
ecf709
+    if (ret != EOK) {
ecf709
+        goto done;
ecf709
+    }
ecf709
+
ecf709
+    ret = nss_protocol_fill_name_list_all_domains(cmd_ctx->nss_ctx, cmd_ctx,
ecf709
+                                                  pctx->creq->out, results);
ecf709
+    if (ret != EOK) {
ecf709
+        goto done;
ecf709
+    }
ecf709
+
ecf709
+    sss_packet_set_error(pctx->creq->out, EOK);
ecf709
+
ecf709
+done:
ecf709
+    nss_protocol_done(cmd_ctx->cli_ctx, ret);
ecf709
+    talloc_free(cmd_ctx);
ecf709
+}
ecf709
+
ecf709
 static errno_t nss_getby_cert(struct cli_ctx *cli_ctx,
ecf709
                               enum cache_req_type type,
ecf709
                               nss_protocol_fill_packet_fn fill_fn)
ecf709
@@ -934,8 +1018,7 @@ static errno_t nss_cmd_getnamebycert(struct cli_ctx *cli_ctx)
ecf709
 
ecf709
 static errno_t nss_cmd_getlistbycert(struct cli_ctx *cli_ctx)
ecf709
 {
ecf709
-    return nss_getby_cert(cli_ctx, CACHE_REQ_USER_BY_CERT,
ecf709
-                          nss_protocol_fill_name_list);
ecf709
+    return nss_getlistby_cert(cli_ctx, CACHE_REQ_USER_BY_CERT);
ecf709
 }
ecf709
 
ecf709
 struct sss_cmd_table *get_nss_cmds(void)
ecf709
diff --git a/src/responder/nss/nss_protocol.h b/src/responder/nss/nss_protocol.h
ecf709
index e4c0e52c0e642e885ef2c8423ea564beff7242cf..417b0891615dcb8771d49f7b2f4d276342ca3150 100644
ecf709
--- a/src/responder/nss/nss_protocol.h
ecf709
+++ b/src/responder/nss/nss_protocol.h
ecf709
@@ -181,6 +181,12 @@ nss_protocol_fill_name_list(struct nss_ctx *nss_ctx,
ecf709
                             struct cache_req_result *result);
ecf709
 
ecf709
 errno_t
ecf709
+nss_protocol_fill_name_list_all_domains(struct nss_ctx *nss_ctx,
ecf709
+                                        struct nss_cmd_ctx *cmd_ctx,
ecf709
+                                        struct sss_packet *packet,
ecf709
+                                        struct cache_req_result **results);
ecf709
+
ecf709
+errno_t
ecf709
 nss_protocol_fill_id(struct nss_ctx *nss_ctx,
ecf709
                      struct nss_cmd_ctx *cmd_ctx,
ecf709
                      struct sss_packet *packet,
ecf709
diff --git a/src/responder/nss/nss_protocol_sid.c b/src/responder/nss/nss_protocol_sid.c
ecf709
index d4b7ee22d7c68a9e6f7c668f7268cdc5f36768b3..61357c2bf92e2f15d978b64a15ad5bd5aa354445 100644
ecf709
--- a/src/responder/nss/nss_protocol_sid.c
ecf709
+++ b/src/responder/nss/nss_protocol_sid.c
ecf709
@@ -561,3 +561,81 @@ nss_protocol_fill_name_list(struct nss_ctx *nss_ctx,
ecf709
 
ecf709
     return EOK;
ecf709
 }
ecf709
+
ecf709
+errno_t
ecf709
+nss_protocol_fill_name_list_all_domains(struct nss_ctx *nss_ctx,
ecf709
+                                        struct nss_cmd_ctx *cmd_ctx,
ecf709
+                                        struct sss_packet *packet,
ecf709
+                                        struct cache_req_result **results)
ecf709
+{
ecf709
+    enum sss_id_type *id_types;
ecf709
+    size_t rp = 0;
ecf709
+    size_t body_len;
ecf709
+    uint8_t *body;
ecf709
+    errno_t ret;
ecf709
+    struct sized_string *sz_names;
ecf709
+    size_t len;
ecf709
+    size_t c;
ecf709
+    const char *tmp_str;
ecf709
+    size_t d;
ecf709
+    size_t total = 0;
ecf709
+    size_t iter = 0;
ecf709
+
ecf709
+    if (results == NULL) {
ecf709
+        return EINVAL;
ecf709
+    }
ecf709
+
ecf709
+    for (d = 0; results[d] != NULL; d++) {
ecf709
+        total += results[d]->count;
ecf709
+    }
ecf709
+
ecf709
+    sz_names = talloc_array(cmd_ctx, struct sized_string, total);
ecf709
+    if (sz_names == NULL) {
ecf709
+        return ENOMEM;
ecf709
+    }
ecf709
+
ecf709
+    id_types = talloc_array(cmd_ctx, enum sss_id_type, total);
ecf709
+    if (id_types == NULL) {
ecf709
+        return ENOMEM;
ecf709
+    }
ecf709
+
ecf709
+    len = 0;
ecf709
+    for (d = 0; results[d] != NULL; d++) {
ecf709
+        for (c = 0; c < results[d]->count; c++) {
ecf709
+            ret = nss_get_id_type(cmd_ctx, results[d], &(id_types[iter]));
ecf709
+            if (ret != EOK) {
ecf709
+                return ret;
ecf709
+            }
ecf709
+
ecf709
+            tmp_str = sss_get_name_from_msg(results[d]->domain,
ecf709
+                                            results[d]->msgs[c]);
ecf709
+            if (tmp_str == NULL) {
ecf709
+                return EINVAL;
ecf709
+            }
ecf709
+            to_sized_string(&(sz_names[iter]), tmp_str);
ecf709
+
ecf709
+            len += sz_names[iter].len;
ecf709
+            iter++;
ecf709
+        }
ecf709
+    }
ecf709
+
ecf709
+    len += (2 + total) * sizeof(uint32_t);
ecf709
+
ecf709
+    ret = sss_packet_grow(packet, len);
ecf709
+    if (ret != EOK) {
ecf709
+        DEBUG(SSSDBG_OP_FAILURE, "sss_packet_grow failed.\n");
ecf709
+        return ret;
ecf709
+    }
ecf709
+
ecf709
+    sss_packet_get_body(packet, &body, &body_len);
ecf709
+
ecf709
+    SAFEALIGN_SET_UINT32(&body[rp], total, &rp); /* Num results. */
ecf709
+    SAFEALIGN_SET_UINT32(&body[rp], 0, &rp); /* Reserved. */
ecf709
+    for (c = 0; c < total; c++) {
ecf709
+        SAFEALIGN_SET_UINT32(&body[rp], id_types[c], &rp);
ecf709
+        SAFEALIGN_SET_STRING(&body[rp], sz_names[c].str, sz_names[c].len,
ecf709
+                             &rp);
ecf709
+    }
ecf709
+
ecf709
+    return EOK;
ecf709
+}
ecf709
diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c
ecf709
index 8c72f44f1869558893627e1f2f91b5f3b96c6317..03b5bcc302322551a32f5b8cfe4b7698947abbe7 100644
ecf709
--- a/src/tests/cmocka/test_nss_srv.c
ecf709
+++ b/src/tests/cmocka/test_nss_srv.c
ecf709
@@ -3808,7 +3808,8 @@ static int test_nss_getnamebycert_check(uint32_t status, uint8_t *body, size_t b
ecf709
     return EOK;
ecf709
 }
ecf709
 
ecf709
-static int test_nss_getlistbycert_check(uint32_t status, uint8_t *body, size_t blen)
ecf709
+static int test_nss_getlistbycert_check_exp(uint32_t status, uint8_t *body,
ecf709
+                                            size_t blen, size_t exp)
ecf709
 {
ecf709
     size_t rp = 0;
ecf709
     uint32_t id_type;
ecf709
@@ -3817,13 +3818,13 @@ static int test_nss_getlistbycert_check(uint32_t status, uint8_t *body, size_t b
ecf709
     const char *name;
ecf709
     int found = 0;
ecf709
     const char *fq_name1 = "testcertuser@"TEST_DOM_NAME ;
ecf709
-    const char *fq_name2 = "testcertuser2@"TEST_DOM_NAME;
ecf709
+    const char *fq_name2 = "testcertuser2@"TEST_SUBDOM_NAME;
ecf709
 
ecf709
     assert_int_equal(status, EOK);
ecf709
 
ecf709
     /* num_results and reserved */
ecf709
     SAFEALIGN_COPY_UINT32(&num, body + rp, &rp);
ecf709
-    assert_in_range(num, 1, 2);
ecf709
+    assert_int_equal(num, exp);
ecf709
     SAFEALIGN_COPY_UINT32(&reserved, body + rp, &rp);
ecf709
     assert_int_equal(reserved, 0);
ecf709
 
ecf709
@@ -3858,6 +3859,17 @@ static int test_nss_getlistbycert_check(uint32_t status, uint8_t *body, size_t b
ecf709
     return EOK;
ecf709
 }
ecf709
 
ecf709
+static int test_nss_getlistbycert_check_one(uint32_t status, uint8_t *body,
ecf709
+                                            size_t blen)
ecf709
+{
ecf709
+    return test_nss_getlistbycert_check_exp(status, body, blen, 1);
ecf709
+}
ecf709
+
ecf709
+static int test_nss_getlistbycert_check_two(uint32_t status, uint8_t *body,
ecf709
+                                            size_t blen)
ecf709
+{
ecf709
+    return test_nss_getlistbycert_check_exp(status, body, blen, 2);
ecf709
+}
ecf709
 
ecf709
 static void test_nss_getnamebycert(void **state)
ecf709
 {
ecf709
@@ -3949,7 +3961,7 @@ static void test_nss_getlistbycert(void **state)
ecf709
     der = sss_base64_decode(nss_test_ctx, TEST_TOKEN_CERT, &der_size);
ecf709
     assert_non_null(der);
ecf709
 
ecf709
-    ret = sysdb_attrs_add_mem(attrs, SYSDB_USER_CERT, der, der_size);
ecf709
+    ret = sysdb_attrs_add_mem(attrs, SYSDB_USER_MAPPED_CERT, der, der_size);
ecf709
     talloc_free(der);
ecf709
     assert_int_equal(ret, EOK);
ecf709
 
ecf709
@@ -3967,7 +3979,7 @@ static void test_nss_getlistbycert(void **state)
ecf709
     /* Should go straight to back end, without contacting DP. */
ecf709
     /* If there is only a single user mapped the result will look like the */
ecf709
     /* result of getnamebycert. */
ecf709
-    set_cmd_cb(test_nss_getlistbycert_check);
ecf709
+    set_cmd_cb(test_nss_getlistbycert_check_one);
ecf709
     ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETLISTBYCERT,
ecf709
                           nss_test_ctx->nss_cmds);
ecf709
     assert_int_equal(ret, EOK);
ecf709
@@ -3990,7 +4002,7 @@ static void test_nss_getlistbycert_multi(void **state)
ecf709
     attrs = sysdb_new_attrs(nss_test_ctx);
ecf709
     assert_non_null(attrs);
ecf709
 
ecf709
-    ret = sysdb_attrs_add_mem(attrs, SYSDB_USER_CERT, der, der_size);
ecf709
+    ret = sysdb_attrs_add_mem(attrs, SYSDB_USER_MAPPED_CERT, der, der_size);
ecf709
     assert_int_equal(ret, EOK);
ecf709
 
ecf709
     /* Prime the cache with two valid user */
ecf709
@@ -4004,11 +4016,11 @@ static void test_nss_getlistbycert_multi(void **state)
ecf709
     attrs = sysdb_new_attrs(nss_test_ctx);
ecf709
     assert_non_null(attrs);
ecf709
 
ecf709
-    ret = sysdb_attrs_add_mem(attrs, SYSDB_USER_CERT, der, der_size);
ecf709
+    ret = sysdb_attrs_add_mem(attrs, SYSDB_USER_MAPPED_CERT, der, der_size);
ecf709
     talloc_free(der);
ecf709
     assert_int_equal(ret, EOK);
ecf709
 
ecf709
-    ret = store_user(nss_test_ctx, nss_test_ctx->tctx->dom,
ecf709
+    ret = store_user(nss_test_ctx, nss_test_ctx->subdom,
ecf709
                      &testbycert2, attrs, 0);
ecf709
     assert_int_equal(ret, EOK);
ecf709
     talloc_free(attrs);
ecf709
@@ -4019,7 +4031,7 @@ static void test_nss_getlistbycert_multi(void **state)
ecf709
 
ecf709
     /* Query for that user, call a callback when command finishes */
ecf709
     /* Should go straight to back end, without contacting DP */
ecf709
-    set_cmd_cb(test_nss_getlistbycert_check);
ecf709
+    set_cmd_cb(test_nss_getlistbycert_check_two);
ecf709
     ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETLISTBYCERT,
ecf709
                           nss_test_ctx->nss_cmds);
ecf709
     assert_int_equal(ret, EOK);
ecf709
@@ -4290,7 +4302,8 @@ int main(int argc, const char *argv[])
ecf709
         cmocka_unit_test_setup_teardown(test_nss_getlistbycert,
ecf709
                                         nss_test_setup, nss_test_teardown),
ecf709
         cmocka_unit_test_setup_teardown(test_nss_getlistbycert_multi,
ecf709
-                                        nss_test_setup, nss_test_teardown),
ecf709
+                                        nss_subdom_test_setup,
ecf709
+                                        nss_subdom_test_teardown),
ecf709
         cmocka_unit_test_setup_teardown(test_nss_getsidbyname,
ecf709
                                         nss_test_setup, nss_test_teardown),
ecf709
         cmocka_unit_test_setup_teardown(test_nss_getsidbyupn,
ecf709
-- 
ecf709
2.9.3
ecf709