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

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