summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/responder/nss/nsssrv_cmd.c120
-rw-r--r--src/tests/cmocka/test_nss_srv.c133
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. */