diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/responder/nss/nsssrv_cmd.c | 120 | ||||
-rw-r--r-- | src/tests/cmocka/test_nss_srv.c | 133 |
2 files changed, 223 insertions, 30 deletions
diff --git a/src/responder/nss/nsssrv_cmd.c b/src/responder/nss/nsssrv_cmd.c index 4ac5eb91e..b100aae08 100644 --- a/src/responder/nss/nsssrv_cmd.c +++ b/src/responder/nss/nsssrv_cmd.c @@ -4148,18 +4148,19 @@ static errno_t nss_cmd_getsidby_search(struct nss_dom_ctx *dctx) struct nss_ctx *nctx; int ret; int err; - const char *attrs[] = {SYSDB_NAME, SYSDB_OBJECTCLASS, SYSDB_SID_STR, - ORIGINALAD_PREFIX SYSDB_NAME, - ORIGINALAD_PREFIX SYSDB_UIDNUM, - ORIGINALAD_PREFIX SYSDB_GIDNUM, - ORIGINALAD_PREFIX SYSDB_GECOS, - ORIGINALAD_PREFIX SYSDB_HOMEDIR, - ORIGINALAD_PREFIX SYSDB_SHELL, - SYSDB_UPN, - SYSDB_DEFAULT_OVERRIDE_NAME, - SYSDB_AD_ACCOUNT_EXPIRES, - SYSDB_AD_USER_ACCOUNT_CONTROL, - SYSDB_DEFAULT_ATTRS, NULL}; + const char *default_attrs[] = {SYSDB_NAME, SYSDB_OBJECTCLASS, SYSDB_SID_STR, + ORIGINALAD_PREFIX SYSDB_NAME, + ORIGINALAD_PREFIX SYSDB_UIDNUM, + ORIGINALAD_PREFIX SYSDB_GIDNUM, + ORIGINALAD_PREFIX SYSDB_GECOS, + ORIGINALAD_PREFIX SYSDB_HOMEDIR, + ORIGINALAD_PREFIX SYSDB_SHELL, + SYSDB_UPN, + SYSDB_DEFAULT_OVERRIDE_NAME, + SYSDB_AD_ACCOUNT_EXPIRES, + SYSDB_AD_USER_ACCOUNT_CONTROL, + SYSDB_DEFAULT_ATTRS, NULL}; + const char **attrs; bool user_found = false; bool group_found = false; struct ldb_message *msg = NULL; @@ -4281,6 +4282,18 @@ static errno_t nss_cmd_getsidby_search(struct nss_dom_ctx *dctx) goto done; } + attrs = default_attrs; + if (cmdctx->cmd == SSS_NSS_GETORIGBYNAME + && nctx->extra_attributes != NULL) { + ret = add_strings_lists(cmdctx, default_attrs, + nctx->extra_attributes, false, + discard_const(&attrs)); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, "add_strings_lists failed.\n"); + goto done; + } + } + if (cmdctx->cmd == SSS_NSS_GETSIDBYID) { ret = sysdb_search_user_by_uid(cmdctx, dom, cmdctx->id, attrs, &msg); @@ -4593,16 +4606,21 @@ static errno_t fill_sid(struct sss_packet *packet, } static errno_t fill_orig(struct sss_packet *packet, + struct resp_ctx *rctx, enum sss_id_type id_type, struct ldb_message *msg) { 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 sum; + size_t found; + size_t extra_attrs_count = 0; + const char **extra_attrs_list = NULL; const char *orig_attr_list[] = {SYSDB_SID_STR, ORIGINALAD_PREFIX SYSDB_NAME, ORIGINALAD_PREFIX SYSDB_UIDNUM, @@ -4615,42 +4633,83 @@ static errno_t fill_orig(struct sss_packet *packet, SYSDB_AD_ACCOUNT_EXPIRES, SYSDB_AD_USER_ACCOUNT_CONTROL, NULL}; - struct sized_string keys[sizeof(orig_attr_list)]; - struct sized_string vals[sizeof(orig_attr_list)]; + struct sized_string *keys; + struct sized_string *vals; + struct nss_ctx *nctx; + + tmp_ctx = talloc_new(NULL); + if (tmp_ctx == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n"); + return ENOMEM; + } + + nctx = talloc_get_type(rctx->pvt_ctx, struct nss_ctx); + if (nctx->extra_attributes != NULL) { + extra_attrs_list = nctx->extra_attributes; + for(extra_attrs_count = 0; + extra_attrs_list[extra_attrs_count] != NULL; + 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); + if (keys == NULL || vals == NULL) { + DEBUG(SSSDBG_OP_FAILURE, "talloc_array failed.\n"); + ret = ENOMEM; + goto done; + } 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[c], orig_attr_list[c]); - sum += keys[c].len; - to_sized_string(&vals[c], tmp_str); - sum += vals[c].len; - } else { - vals[c].len = 0; + to_sized_string(&keys[found], orig_attr_list[c]); + sum += keys[found].len; + to_sized_string(&vals[found], tmp_str); + sum += vals[found].len; + + 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++; } } ret = sss_packet_grow(packet, sum + 3 * sizeof(uint32_t)); if (ret != EOK) { DEBUG(SSSDBG_OP_FAILURE, "sss_packet_grow failed.\n"); - return ret; + goto done; } sss_packet_get_body(packet, &body, &blen); SAFEALIGN_SETMEM_UINT32(body, 1, &pctr); /* Num results */ SAFEALIGN_SETMEM_UINT32(body + pctr, 0, &pctr); /* reserved */ SAFEALIGN_COPY_UINT32(body + pctr, &id_type, &pctr); - for (c = 0; orig_attr_list[c] != NULL; c++) { - if (vals[c].len != 0) { - memcpy(&body[pctr], keys[c].str, keys[c].len); - pctr+= keys[c].len; - memcpy(&body[pctr], vals[c].str, vals[c].len); - pctr+= vals[c].len; - } + for (c = 0; c < found; c++) { + memcpy(&body[pctr], keys[c].str, keys[c].len); + pctr+= keys[c].len; + memcpy(&body[pctr], vals[c].str, vals[c].len); + pctr+= vals[c].len; } - return EOK; + ret = EOK; + +done: + talloc_free(tmp_ctx); + + return ret; } static errno_t fill_name(struct sss_packet *packet, @@ -4818,7 +4877,8 @@ static errno_t nss_cmd_getbysid_send_reply(struct nss_dom_ctx *dctx) ret = fill_sid(cctx->creq->out, id_type, dctx->res->msgs[0]); break; case SSS_NSS_GETORIGBYNAME: - ret = fill_orig(cctx->creq->out, id_type, dctx->res->msgs[0]); + ret = fill_orig(cctx->creq->out, cctx->rctx, id_type, + dctx->res->msgs[0]); break; default: DEBUG(SSSDBG_CRIT_FAILURE, "Unsupported request type.\n"); diff --git a/src/tests/cmocka/test_nss_srv.c b/src/tests/cmocka/test_nss_srv.c index 65298cdf0..c318d94be 100644 --- a/src/tests/cmocka/test_nss_srv.c +++ b/src/tests/cmocka/test_nss_srv.c @@ -52,6 +52,8 @@ struct nss_test_ctx { bool ncache_hit; }; +const char *global_extra_attrs[] = {"phone", "mobile", NULL}; + struct nss_test_ctx *nss_test_ctx; /* Mock NSS structure */ @@ -1000,6 +1002,7 @@ void test_nss_setup(struct sss_test_conf_param params[], nss_test_ctx->rctx = mock_rctx(nss_test_ctx, nss_test_ctx->tctx->ev, nss_test_ctx->tctx->dom, nss_test_ctx->nctx); assert_non_null(nss_test_ctx->rctx); + nss_test_ctx->rctx->cdb = nss_test_ctx->tctx->confdb; nss_test_ctx->nctx->rctx = nss_test_ctx->rctx; /* Create client context */ @@ -1827,6 +1830,122 @@ void test_nss_getorigbyname(void **state) assert_int_equal(ret, EOK); } +static int test_nss_getorigbyname_extra_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, "phone"); + rp += strlen(s) + 1; + assert_true(rp < blen); + + s = (char *) body+rp; + assert_string_equal(s, "+12-34 56 78"); + rp += strlen(s) + 1; + assert_true(rp < blen); + + s = (char *) body+rp; + assert_string_equal(s, "mobile"); + rp += strlen(s) + 1; + assert_true(rp < blen); + + s = (char *) body+rp; + assert_string_equal(s, "+98-76 54 32"); + rp += strlen(s) + 1; + assert_int_equal(rp, blen); + + return EOK; +} + +void test_nss_getorigbyname_extra_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, "phone", "+12-34 56 78"); + assert_int_equal(ret, EOK); + + ret = sysdb_attrs_add_string(attrs, "mobile", "+98-76 54 32"); + assert_int_equal(ret, EOK); + + ret = sysdb_attrs_add_string(attrs, "not_extra", "abc"); + assert_int_equal(ret, EOK); + + /* Prime the cache with a valid user */ + ret = sysdb_add_user(nss_test_ctx->tctx->dom, + "testuserorigextra", 2345, 6789, + "test user orig extra", + "/home/testuserorigextra", "/bin/sh", NULL, + attrs, 300, 0); + assert_int_equal(ret, EOK); + + mock_input_user_or_group("testuserorigextra"); + 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_extra_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[] = { @@ -1848,6 +1967,18 @@ void nss_fqdn_test_setup(void **state) test_nss_setup(params, state); } +void nss_test_setup_extra_attr(void **state) +{ + struct sss_test_conf_param params[] = { + { "enumerate", "false" }, + { NULL, NULL }, /* Sentinel */ + }; + + test_nss_setup(params, state); + + nss_test_ctx->nctx->extra_attributes = global_extra_attrs; +} + void nss_subdom_test_setup(void **state) { const char *const testdom[4] = { TEST_SUBDOM_NAME, "TEST.SUB", "test", "S-3" }; @@ -1963,6 +2094,8 @@ int main(int argc, const char *argv[]) nss_test_setup, nss_test_teardown), unit_test_setup_teardown(test_nss_getorigbyname, nss_test_setup, nss_test_teardown), + unit_test_setup_teardown(test_nss_getorigbyname_extra_attrs, + nss_test_setup_extra_attr, nss_test_teardown), }; /* Set debug level to invalid value so we can deside if -d 0 was used. */ |