Blame SOURCES/0059-nss-return-user_attributes-in-origbyname-request.patch

905b4d
From 9b6c5e3233cdbd5fce7b6beed0cf057fe3d5da61 Mon Sep 17 00:00:00 2001
905b4d
From: Sumit Bose <sbose@redhat.com>
905b4d
Date: Fri, 24 Oct 2014 11:30:33 +0200
905b4d
Subject: [PATCH 59/64] nss: return user_attributes in origbyname request
905b4d
905b4d
To allow IPA clients to offer special attributes of AD users form
905b4d
trusted domain the extdom plugin on the IPA server must send them to the
905b4d
clients. The extdom plugin already uses sss_nss_getorigbyname() to get
905b4d
attributes like the SID and the user principal name. This patch adds the
905b4d
attributes given by the NSS/IFP user_attributes option to the list of
905b4d
attributes returned by sss_nss_getorigbyname().
905b4d
905b4d
Fixes https://fedorahosted.org/sssd/ticket/2464
905b4d
905b4d
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
905b4d
---
905b4d
 src/responder/nss/nsssrv_cmd.c  | 120 +++++++++++++++++++++++++++---------
905b4d
 src/tests/cmocka/test_nss_srv.c | 133 ++++++++++++++++++++++++++++++++++++++++
905b4d
 2 files changed, 223 insertions(+), 30 deletions(-)
905b4d
905b4d
diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c
905b4d
index 4ac5eb91eab80291e60afad2bf9c65edfbc21e7d..b100aae08fc04ccf1a295745767c5445cf2e01be 100644
905b4d
--- a/src/responder/nss/nsssrv_cmd.c
905b4d
+++ b/src/responder/nss/nsssrv_cmd.c
905b4d
@@ -4148,18 +4148,19 @@ static errno_t nss_cmd_getsidby_search(struct nss_dom_ctx *dctx)
905b4d
     struct nss_ctx *nctx;
905b4d
     int ret;
905b4d
     int err;
905b4d
-    const char *attrs[] = {SYSDB_NAME, SYSDB_OBJECTCLASS, SYSDB_SID_STR,
905b4d
-                           ORIGINALAD_PREFIX SYSDB_NAME,
905b4d
-                           ORIGINALAD_PREFIX SYSDB_UIDNUM,
905b4d
-                           ORIGINALAD_PREFIX SYSDB_GIDNUM,
905b4d
-                           ORIGINALAD_PREFIX SYSDB_GECOS,
905b4d
-                           ORIGINALAD_PREFIX SYSDB_HOMEDIR,
905b4d
-                           ORIGINALAD_PREFIX SYSDB_SHELL,
905b4d
-                           SYSDB_UPN,
905b4d
-                           SYSDB_DEFAULT_OVERRIDE_NAME,
905b4d
-                           SYSDB_AD_ACCOUNT_EXPIRES,
905b4d
-                           SYSDB_AD_USER_ACCOUNT_CONTROL,
905b4d
-                           SYSDB_DEFAULT_ATTRS, NULL};
905b4d
+    const char *default_attrs[] = {SYSDB_NAME, SYSDB_OBJECTCLASS, SYSDB_SID_STR,
905b4d
+                                   ORIGINALAD_PREFIX SYSDB_NAME,
905b4d
+                                   ORIGINALAD_PREFIX SYSDB_UIDNUM,
905b4d
+                                   ORIGINALAD_PREFIX SYSDB_GIDNUM,
905b4d
+                                   ORIGINALAD_PREFIX SYSDB_GECOS,
905b4d
+                                   ORIGINALAD_PREFIX SYSDB_HOMEDIR,
905b4d
+                                   ORIGINALAD_PREFIX SYSDB_SHELL,
905b4d
+                                   SYSDB_UPN,
905b4d
+                                   SYSDB_DEFAULT_OVERRIDE_NAME,
905b4d
+                                   SYSDB_AD_ACCOUNT_EXPIRES,
905b4d
+                                   SYSDB_AD_USER_ACCOUNT_CONTROL,
905b4d
+                                   SYSDB_DEFAULT_ATTRS, NULL};
905b4d
+    const char **attrs;
905b4d
     bool user_found = false;
905b4d
     bool group_found = false;
905b4d
     struct ldb_message *msg = NULL;
905b4d
@@ -4281,6 +4282,18 @@ static errno_t nss_cmd_getsidby_search(struct nss_dom_ctx *dctx)
905b4d
             goto done;
905b4d
         }
905b4d
 
905b4d
+        attrs = default_attrs;
905b4d
+        if (cmdctx->cmd == SSS_NSS_GETORIGBYNAME
905b4d
+                && nctx->extra_attributes != NULL) {
905b4d
+            ret = add_strings_lists(cmdctx, default_attrs,
905b4d
+                                    nctx->extra_attributes, false,
905b4d
+                                    discard_const(&attrs));
905b4d
+            if (ret != EOK) {
905b4d
+                DEBUG(SSSDBG_OP_FAILURE, "add_strings_lists failed.\n");
905b4d
+                goto done;
905b4d
+            }
905b4d
+        }
905b4d
+
905b4d
         if (cmdctx->cmd == SSS_NSS_GETSIDBYID) {
905b4d
             ret = sysdb_search_user_by_uid(cmdctx, dom, cmdctx->id, attrs,
905b4d
                                            &msg;;
905b4d
@@ -4593,16 +4606,21 @@ static errno_t fill_sid(struct sss_packet *packet,
905b4d
 }
905b4d
 
905b4d
 static errno_t fill_orig(struct sss_packet *packet,
905b4d
+                         struct resp_ctx *rctx,
905b4d
                          enum sss_id_type id_type,
905b4d
                          struct ldb_message *msg)
905b4d
 {
905b4d
     int ret;
905b4d
+    TALLOC_CTX *tmp_ctx;
905b4d
     const char *tmp_str;
905b4d
     uint8_t *body;
905b4d
     size_t blen;
905b4d
     size_t pctr = 0;
905b4d
     size_t c;
905b4d
     size_t sum;
905b4d
+    size_t found;
905b4d
+    size_t extra_attrs_count = 0;
905b4d
+    const char **extra_attrs_list = NULL;
905b4d
     const char *orig_attr_list[] = {SYSDB_SID_STR,
905b4d
                                     ORIGINALAD_PREFIX SYSDB_NAME,
905b4d
                                     ORIGINALAD_PREFIX SYSDB_UIDNUM,
905b4d
@@ -4615,42 +4633,83 @@ static errno_t fill_orig(struct sss_packet *packet,
905b4d
                                     SYSDB_AD_ACCOUNT_EXPIRES,
905b4d
                                     SYSDB_AD_USER_ACCOUNT_CONTROL,
905b4d
                                     NULL};
905b4d
-    struct sized_string keys[sizeof(orig_attr_list)];
905b4d
-    struct sized_string vals[sizeof(orig_attr_list)];
905b4d
+    struct sized_string *keys;
905b4d
+    struct sized_string *vals;
905b4d
+    struct nss_ctx *nctx;
905b4d
+
905b4d
+    tmp_ctx = talloc_new(NULL);
905b4d
+    if (tmp_ctx == NULL) {
905b4d
+        DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
905b4d
+        return ENOMEM;
905b4d
+    }
905b4d
+
905b4d
+    nctx = talloc_get_type(rctx->pvt_ctx, struct nss_ctx);
905b4d
+    if (nctx->extra_attributes != NULL) {
905b4d
+        extra_attrs_list = nctx->extra_attributes;
905b4d
+            for(extra_attrs_count = 0;
905b4d
+                extra_attrs_list[extra_attrs_count] != NULL;
905b4d
+                extra_attrs_count++);
905b4d
+    }
905b4d
+
905b4d
+    keys = talloc_array(tmp_ctx, struct sized_string,
905b4d
+                        sizeof(orig_attr_list) + extra_attrs_count);
905b4d
+    vals = talloc_array(tmp_ctx, struct sized_string,
905b4d
+                        sizeof(orig_attr_list) + extra_attrs_count);
905b4d
+    if (keys == NULL || vals == NULL) {
905b4d
+        DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n");
905b4d
+        ret = ENOMEM;
905b4d
+        goto done;
905b4d
+    }
905b4d
 
905b4d
     sum = 0;
905b4d
+    found = 0;
905b4d
     for (c = 0; orig_attr_list[c] != NULL; c++) {
905b4d
         tmp_str = ldb_msg_find_attr_as_string(msg, orig_attr_list[c], NULL);
905b4d
         if (tmp_str != NULL) {
905b4d
-            to_sized_string(&keys[c], orig_attr_list[c]);
905b4d
-            sum += keys[c].len;
905b4d
-            to_sized_string(&vals[c], tmp_str);
905b4d
-            sum += vals[c].len;
905b4d
-        } else {
905b4d
-            vals[c].len = 0;
905b4d
+            to_sized_string(&keys[found], orig_attr_list[c]);
905b4d
+            sum += keys[found].len;
905b4d
+            to_sized_string(&vals[found], tmp_str);
905b4d
+            sum += vals[found].len;
905b4d
+
905b4d
+            found++;
905b4d
+        }
905b4d
+    }
905b4d
+
905b4d
+    for (c = 0; c < extra_attrs_count; c++) {
905b4d
+        tmp_str = ldb_msg_find_attr_as_string(msg, extra_attrs_list[c], NULL);
905b4d
+        if (tmp_str != NULL) {
905b4d
+            to_sized_string(&keys[found], extra_attrs_list[c]);
905b4d
+            sum += keys[found].len;
905b4d
+            to_sized_string(&vals[found], tmp_str);
905b4d
+            sum += vals[found].len;
905b4d
+
905b4d
+            found++;
905b4d
         }
905b4d
     }
905b4d
 
905b4d
     ret = sss_packet_grow(packet, sum +  3 * sizeof(uint32_t));
905b4d
     if (ret != EOK) {
905b4d
         DEBUG(SSSDBG_OP_FAILURE, "sss_packet_grow failed.\n");
905b4d
-        return ret;
905b4d
+        goto done;
905b4d
     }
905b4d
 
905b4d
     sss_packet_get_body(packet, &body, &blen);
905b4d
     SAFEALIGN_SETMEM_UINT32(body, 1, &pctr); /* Num results */
905b4d
     SAFEALIGN_SETMEM_UINT32(body + pctr, 0, &pctr); /* reserved */
905b4d
     SAFEALIGN_COPY_UINT32(body + pctr, &id_type, &pctr);
905b4d
-    for (c = 0; orig_attr_list[c] != NULL; c++) {
905b4d
-        if (vals[c].len != 0) {
905b4d
-            memcpy(&body[pctr], keys[c].str, keys[c].len);
905b4d
-            pctr+= keys[c].len;
905b4d
-            memcpy(&body[pctr], vals[c].str, vals[c].len);
905b4d
-            pctr+= vals[c].len;
905b4d
-        }
905b4d
+    for (c = 0; c < found; c++) {
905b4d
+        memcpy(&body[pctr], keys[c].str, keys[c].len);
905b4d
+        pctr+= keys[c].len;
905b4d
+        memcpy(&body[pctr], vals[c].str, vals[c].len);
905b4d
+        pctr+= vals[c].len;
905b4d
     }
905b4d
 
905b4d
-    return EOK;
905b4d
+    ret = EOK;
905b4d
+
905b4d
+done:
905b4d
+    talloc_free(tmp_ctx);
905b4d
+
905b4d
+    return ret;
905b4d
 }
905b4d
 
905b4d
 static errno_t fill_name(struct sss_packet *packet,
905b4d
@@ -4818,7 +4877,8 @@ static errno_t nss_cmd_getbysid_send_reply(struct nss_dom_ctx *dctx)
905b4d
         ret = fill_sid(cctx->creq->out, id_type, dctx->res->msgs[0]);
905b4d
         break;
905b4d
     case SSS_NSS_GETORIGBYNAME:
905b4d
-        ret = fill_orig(cctx->creq->out, id_type, dctx->res->msgs[0]);
905b4d
+        ret = fill_orig(cctx->creq->out, cctx->rctx, id_type,
905b4d
+                        dctx->res->msgs[0]);
905b4d
         break;
905b4d
     default:
905b4d
         DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported request type.\n");
905b4d
diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c
905b4d
index 65298cdf04e37e85820d3308c773f1c95a21ce31..c318d94be867bbb9991de288cdae45d2ddc29b24 100644
905b4d
--- a/src/tests/cmocka/test_nss_srv.c
905b4d
+++ b/src/tests/cmocka/test_nss_srv.c
905b4d
@@ -52,6 +52,8 @@ struct nss_test_ctx {
905b4d
     bool ncache_hit;
905b4d
 };
905b4d
 
905b4d
+const char *global_extra_attrs[] = {"phone", "mobile", NULL};
905b4d
+
905b4d
 struct nss_test_ctx *nss_test_ctx;
905b4d
 
905b4d
 /* Mock NSS structure */
905b4d
@@ -1000,6 +1002,7 @@ void test_nss_setup(struct sss_test_conf_param params[],
905b4d
     nss_test_ctx->rctx = mock_rctx(nss_test_ctx, nss_test_ctx->tctx->ev,
905b4d
                                    nss_test_ctx->tctx->dom, nss_test_ctx->nctx);
905b4d
     assert_non_null(nss_test_ctx->rctx);
905b4d
+    nss_test_ctx->rctx->cdb = nss_test_ctx->tctx->confdb;
905b4d
     nss_test_ctx->nctx->rctx = nss_test_ctx->rctx;
905b4d
 
905b4d
     /* Create client context */
905b4d
@@ -1827,6 +1830,122 @@ void test_nss_getorigbyname(void **state)
905b4d
     assert_int_equal(ret, EOK);
905b4d
 }
905b4d
 
905b4d
+static int test_nss_getorigbyname_extra_check(uint32_t status, uint8_t *body,
905b4d
+                                              size_t blen)
905b4d
+{
905b4d
+    const char *s;
905b4d
+    enum sss_id_type id_type;
905b4d
+    size_t rp = 2 * sizeof(uint32_t);
905b4d
+
905b4d
+    assert_int_equal(status, EOK);
905b4d
+
905b4d
+    SAFEALIGN_COPY_UINT32(&id_type, body+rp, &rp);
905b4d
+    assert_int_equal(id_type, SSS_ID_TYPE_UID);
905b4d
+
905b4d
+    /* Sequence of null terminated strings */
905b4d
+    s = (char *) body+rp;
905b4d
+    assert_string_equal(s, SYSDB_SID_STR);
905b4d
+    rp += strlen(s) + 1;
905b4d
+    assert_true(rp < blen);
905b4d
+
905b4d
+    s = (char *) body+rp;
905b4d
+    assert_string_equal(s, "S-1-2-3-4");
905b4d
+    rp += strlen(s) + 1;
905b4d
+    assert_true(rp < blen);
905b4d
+
905b4d
+    s = (char *) body+rp;
905b4d
+    assert_string_equal(s, ORIGINALAD_PREFIX SYSDB_NAME);
905b4d
+    rp += strlen(s) + 1;
905b4d
+    assert_true(rp < blen);
905b4d
+
905b4d
+    s = (char *) body+rp;
905b4d
+    assert_string_equal(s, "orig_name");
905b4d
+    rp += strlen(s) + 1;
905b4d
+    assert_true(rp < blen);
905b4d
+
905b4d
+    s = (char *) body+rp;
905b4d
+    assert_string_equal(s, ORIGINALAD_PREFIX SYSDB_UIDNUM);
905b4d
+    rp += strlen(s) + 1;
905b4d
+    assert_true(rp < blen);
905b4d
+
905b4d
+    s = (char *) body+rp;
905b4d
+    assert_string_equal(s, "1234");
905b4d
+    rp += strlen(s) + 1;
905b4d
+    assert_true(rp < blen);
905b4d
+
905b4d
+    s = (char *) body+rp;
905b4d
+    assert_string_equal(s, "phone");
905b4d
+    rp += strlen(s) + 1;
905b4d
+    assert_true(rp < blen);
905b4d
+
905b4d
+    s = (char *) body+rp;
905b4d
+    assert_string_equal(s, "+12-34 56 78");
905b4d
+    rp += strlen(s) + 1;
905b4d
+    assert_true(rp < blen);
905b4d
+
905b4d
+    s = (char *) body+rp;
905b4d
+    assert_string_equal(s, "mobile");
905b4d
+    rp += strlen(s) + 1;
905b4d
+    assert_true(rp < blen);
905b4d
+
905b4d
+    s = (char *) body+rp;
905b4d
+    assert_string_equal(s, "+98-76 54 32");
905b4d
+    rp += strlen(s) + 1;
905b4d
+    assert_int_equal(rp, blen);
905b4d
+
905b4d
+    return EOK;
905b4d
+}
905b4d
+
905b4d
+void test_nss_getorigbyname_extra_attrs(void **state)
905b4d
+{
905b4d
+    errno_t ret;
905b4d
+    struct sysdb_attrs *attrs;
905b4d
+
905b4d
+    attrs = sysdb_new_attrs(nss_test_ctx);
905b4d
+    assert_non_null(attrs);
905b4d
+
905b4d
+    ret = sysdb_attrs_add_string(attrs, SYSDB_SID_STR, "S-1-2-3-4");
905b4d
+    assert_int_equal(ret, EOK);
905b4d
+
905b4d
+    ret = sysdb_attrs_add_string(attrs, ORIGINALAD_PREFIX SYSDB_NAME,
905b4d
+                                 "orig_name");
905b4d
+    assert_int_equal(ret, EOK);
905b4d
+
905b4d
+    ret = sysdb_attrs_add_uint32(attrs, ORIGINALAD_PREFIX SYSDB_UIDNUM, 1234);
905b4d
+    assert_int_equal(ret, EOK);
905b4d
+
905b4d
+    ret = sysdb_attrs_add_string(attrs, "phone", "+12-34 56 78");
905b4d
+    assert_int_equal(ret, EOK);
905b4d
+
905b4d
+    ret = sysdb_attrs_add_string(attrs, "mobile", "+98-76 54 32");
905b4d
+    assert_int_equal(ret, EOK);
905b4d
+
905b4d
+    ret = sysdb_attrs_add_string(attrs, "not_extra", "abc");
905b4d
+    assert_int_equal(ret, EOK);
905b4d
+
905b4d
+    /* Prime the cache with a valid user */
905b4d
+    ret = sysdb_add_user(nss_test_ctx->tctx->dom,
905b4d
+                         "testuserorigextra", 2345, 6789,
905b4d
+                         "test user orig extra",
905b4d
+                         "/home/testuserorigextra", "/bin/sh", NULL,
905b4d
+                         attrs, 300, 0);
905b4d
+    assert_int_equal(ret, EOK);
905b4d
+
905b4d
+    mock_input_user_or_group("testuserorigextra");
905b4d
+    will_return(__wrap_sss_packet_get_cmd, SSS_NSS_GETORIGBYNAME);
905b4d
+    will_return(__wrap_sss_packet_get_body, WRAP_CALL_REAL);
905b4d
+
905b4d
+    /* Query for that user, call a callback when command finishes */
905b4d
+    set_cmd_cb(test_nss_getorigbyname_extra_check);
905b4d
+    ret = sss_cmd_execute(nss_test_ctx->cctx, SSS_NSS_GETORIGBYNAME,
905b4d
+                          nss_test_ctx->nss_cmds);
905b4d
+    assert_int_equal(ret, EOK);
905b4d
+
905b4d
+    /* Wait until the test finishes with EOK */
905b4d
+    ret = test_ev_loop(nss_test_ctx->tctx);
905b4d
+    assert_int_equal(ret, EOK);
905b4d
+}
905b4d
+
905b4d
 void nss_test_setup(void **state)
905b4d
 {
905b4d
     struct sss_test_conf_param params[] = {
905b4d
@@ -1848,6 +1967,18 @@ void nss_fqdn_test_setup(void **state)
905b4d
     test_nss_setup(params, state);
905b4d
 }
905b4d
 
905b4d
+void nss_test_setup_extra_attr(void **state)
905b4d
+{
905b4d
+    struct sss_test_conf_param params[] = {
905b4d
+        { "enumerate", "false" },
905b4d
+        { NULL, NULL },             /* Sentinel */
905b4d
+    };
905b4d
+
905b4d
+    test_nss_setup(params, state);
905b4d
+
905b4d
+    nss_test_ctx->nctx->extra_attributes = global_extra_attrs;
905b4d
+}
905b4d
+
905b4d
 void nss_subdom_test_setup(void **state)
905b4d
 {
905b4d
     const char *const testdom[4] = { TEST_SUBDOM_NAME, "TEST.SUB", "test", "S-3" };
905b4d
@@ -1963,6 +2094,8 @@ int main(int argc, const char *argv[])
905b4d
                                  nss_test_setup, nss_test_teardown),
905b4d
         unit_test_setup_teardown(test_nss_getorigbyname,
905b4d
                                  nss_test_setup, nss_test_teardown),
905b4d
+        unit_test_setup_teardown(test_nss_getorigbyname_extra_attrs,
905b4d
+                                 nss_test_setup_extra_attr, nss_test_teardown),
905b4d
     };
905b4d
 
905b4d
     /* Set debug level to invalid value so we can deside if -d 0 was used. */
905b4d
-- 
905b4d
1.9.3
905b4d