diff options
author | Stephen Gallagher <sgallagh@redhat.com> | 2009-02-10 19:29:13 -0500 |
---|---|---|
committer | Simo Sorce <idra@samba.org> | 2009-02-12 17:08:57 -0500 |
commit | b7f8cce6f34cae52260a7eca13e39c2ecd98d77c (patch) | |
tree | 61a6f45ffdcdda256bbe3400f2c1be5fed763242 /server | |
parent | 02618c33c2389922a69ebad38a9ee4143d1986a6 (diff) | |
download | sssd-b7f8cce6f34cae52260a7eca13e39c2ecd98d77c.tar.gz sssd-b7f8cce6f34cae52260a7eca13e39c2ecd98d77c.tar.bz2 sssd-b7f8cce6f34cae52260a7eca13e39c2ecd98d77c.zip |
Adding sysdb_add_acct_to_posix_group and associated unit tests
Diffstat (limited to 'server')
-rw-r--r-- | server/db/sysdb.c | 175 | ||||
-rw-r--r-- | server/db/sysdb.h | 14 | ||||
-rw-r--r-- | server/tests/sysdb-tests.c | 300 |
3 files changed, 462 insertions, 27 deletions
diff --git a/server/db/sysdb.c b/server/db/sysdb.c index 5e94aab8..175bf545 100644 --- a/server/db/sysdb.c +++ b/server/db/sysdb.c @@ -733,9 +733,12 @@ done: int sysdb_store_account_posix(TALLOC_CTX *memctx, struct sysdb_ctx *sysdb, const char *domain, - char *name, char *pwd, + const char *name, + const char *pwd, uid_t uid, gid_t gid, - char *gecos, char *homedir, char *shell) + const char *gecos, + const char *homedir, + const char *shell) { TALLOC_CTX *tmp_ctx; const char *attrs[] = { SYSDB_PW_NAME, NULL }; @@ -1114,10 +1117,9 @@ int sysdb_store_group_posix(TALLOC_CTX *memctx, } group_dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, - "gid=%s,"SYSDB_TMPL_GROUP_BASE, + SYSDB_GR_NAME"=%s,"SYSDB_TMPL_GROUP_BASE, name, domain); if (group_dn == NULL) { - ret = ENOMEM; talloc_free(tmp_ctx); return ENOMEM; } @@ -1261,6 +1263,171 @@ done: return ret; } +int sysdb_add_acct_to_posix_group(TALLOC_CTX *mem_ctx, + struct sysdb_ctx *sysdb, + const char *domain, + const char *gname, + const char *username) +{ + TALLOC_CTX *tmp_ctx; + int ret, lret; + char *account; + struct ldb_dn *acct_dn; + struct ldb_dn *group_dn; + struct ldb_message *msg; + struct ldb_result *res; + struct ldb_request *req; + const char *acct_attrs[] = { SYSDB_PW_NAME, NULL }; + const char *group_attrs[] = { SYSDB_GR_MEMBER, NULL }; + + if (!sysdb || !domain || !gname || !username) { + return EINVAL; + } + + tmp_ctx = talloc_new(mem_ctx); + if (tmp_ctx == NULL) { + return ENOMEM; + } + + account = talloc_asprintf(tmp_ctx, + SYSDB_PW_NAME"=%s,"SYSDB_TMPL_USER_BASE, + username, domain); + if (account == NULL) { + talloc_free(tmp_ctx); + return ENOMEM; + } + acct_dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, account); + if (acct_dn == NULL) { + talloc_free(tmp_ctx); + return ENOMEM; + } + + group_dn = ldb_dn_new_fmt(tmp_ctx, sysdb->ldb, + SYSDB_GR_NAME"=%s,"SYSDB_TMPL_GROUP_BASE, + gname, domain); + if (group_dn == NULL) { + talloc_free(tmp_ctx); + return ENOMEM; + } + ret = EOK; + + /* Start LDB Transaction */ + lret = ldb_transaction_start(sysdb->ldb); + if (lret != LDB_SUCCESS) { + DEBUG(1, ("Failed ldb transaction start !? (%d)\n", lret)); + talloc_free(tmp_ctx); + return EIO; + } + + /* Verify the existence of the user */ + lret = ldb_search(sysdb->ldb, tmp_ctx, &res, acct_dn, + LDB_SCOPE_BASE, acct_attrs, SYSDB_PWENT_FILTER); + if (lret != LDB_SUCCESS) { + DEBUG(1, ("Failed to make search request: %s(%d)[%s]\b", + ldb_strerror(lret), lret, ldb_errstring(sysdb->ldb))); + ret = EIO; + goto done; + } + + switch(res->count) { + case 0: + DEBUG(1, ("No such user to add to group.\n")); + goto done; + break; + + case 1: + /* Exactly one user returned. Proceed */ + break; + + default: + DEBUG(0, ("Cache DB corrupted, base search returned %d results\n", + res->count)); + ret = EIO; + goto done; + } + talloc_free(res); + + /* Verify the existence of the group */ + lret = ldb_search(sysdb->ldb, tmp_ctx, &res, group_dn, + LDB_SCOPE_BASE, group_attrs, SYSDB_GRENT_FILTER); + if (lret != LDB_SUCCESS) { + DEBUG(1, ("Failed to make search request: %s(%d)[%s]\b", + ldb_strerror(lret), lret, ldb_errstring(sysdb->ldb))); + ret = EIO; + goto done; + } + + switch(res->count) { + case 0: + DEBUG(1, ("No such group.\n")); + goto done; + break; + + case 1: + /* Exactly one user returned. Proceed */ + break; + + default: + DEBUG(0, ("Cache DB corrupted, base search returned %d results\n", + res->count)); + ret = EIO; + goto done; + } + talloc_free(res); + + /* Add the user as a member of the group */ + msg = ldb_msg_new(tmp_ctx); + if(msg == NULL) { + ret = ENOMEM; + goto done; + } + msg->dn = group_dn; + lret = ldb_msg_add_empty(msg, SYSDB_GR_MEMBER, LDB_FLAG_MOD_ADD, NULL); + if (lret == LDB_SUCCESS) { + lret = ldb_msg_add_fmt(msg, SYSDB_GR_MEMBER, "%s", account); + } + if (lret != LDB_SUCCESS) { + ret = errno; + goto done; + } + + lret = ldb_build_mod_req(&req, sysdb->ldb, tmp_ctx, msg, NULL, + NULL, ldb_op_default_callback, NULL); + if (lret == LDB_SUCCESS) { + lret = ldb_request(sysdb->ldb, req); + if (lret == LDB_SUCCESS) { + lret = ldb_wait(req->handle, LDB_WAIT_ALL); + } + } + if (lret != LDB_SUCCESS) { + DEBUG(1, ("Failed to make modify request: %s(%d)[%s]\n", + ldb_strerror(lret), lret, ldb_errstring(sysdb->ldb))); + ret = EIO; + goto done; + } + + /* Commit LDB Transaction */ + lret = ldb_transaction_commit(sysdb->ldb); + if (lret != LDB_SUCCESS) { + DEBUG(1, ("Failed ldb transaction start !? (%d)\n", lret)); + ret = EIO; + goto done; + } + + ret = EOK; +done: + /* Cancel LDB Transaction */ + if (ret != EOK) { + lret = ldb_transaction_cancel(sysdb->ldb); + if (lret != LDB_SUCCESS) { + DEBUG(1, ("Failed to cancel ldb transaction (%d)\n", lret)); + } + } + + talloc_free(tmp_ctx); + return ret; +} + int sysdb_init(TALLOC_CTX *mem_ctx, struct event_context *ev, struct confdb_ctx *cdb, diff --git a/server/db/sysdb.h b/server/db/sysdb.h index 582b8abe..19781fb4 100644 --- a/server/db/sysdb.h +++ b/server/db/sysdb.h @@ -50,6 +50,7 @@ #define SYSDB_PW_FULLNAME "fullName" #define SYSDB_PW_HOMEDIR "homeDirectory" #define SYSDB_PW_SHELL "loginShell" +#define SYSDB_PW_MEMBEROF "memberOf" #define SYSDB_GR_NAME "cn" #define SYSDB_GR_GIDNUM "gidNumber" @@ -134,9 +135,12 @@ int sysdb_initgroups(TALLOC_CTX *mem_ctx, int sysdb_store_account_posix(TALLOC_CTX *memctx, struct sysdb_ctx *sysdb, const char *domain, - char *name, char *pwd, + const char *name, + const char *pwd, uid_t uid, gid_t gid, - char *gecos, char *homedir, char *shell); + const char *gecos, + const char *homedir, + const char *shell); int sysdb_remove_account_posix(TALLOC_CTX *memctx, struct sysdb_ctx *sysdb, @@ -150,4 +154,10 @@ int sysdb_store_group_posix(TALLOC_CTX *memctx, struct sysdb_ctx *sysdb, const char *domain, const char *name, gid_t gid); + +int sysdb_add_acct_to_posix_group(TALLOC_CTX *mem_ctx, + struct sysdb_ctx *sysdb, + const char *domain, + const char *gname, + const char *username); #endif /* __SYS_DB_H__ */ diff --git a/server/tests/sysdb-tests.c b/server/tests/sysdb-tests.c index ef49d415..45b4d4f3 100644 --- a/server/tests/sysdb-tests.c +++ b/server/tests/sysdb-tests.c @@ -28,18 +28,20 @@ #include "confdb/confdb.h" #include "db/sysdb.h" +#define SYSDB_POSIX_TEST_GROUP "sysdbtestgroup" + struct sysdb_test_ctx { struct sysdb_ctx *sysdb; struct confdb_ctx *confdb; struct event_context *ev; }; -static int setup_sysdb_tests(TALLOC_CTX *mem_ctx, struct sysdb_test_ctx **ctx) +static int setup_sysdb_tests(struct sysdb_test_ctx **ctx) { struct sysdb_test_ctx *test_ctx; int ret; - test_ctx = talloc_zero(mem_ctx, struct sysdb_test_ctx); + test_ctx = talloc_zero(NULL, struct sysdb_test_ctx); if (test_ctx == NULL) { fail("Could not allocate memory for test context"); return ENOMEM; @@ -56,7 +58,7 @@ static int setup_sysdb_tests(TALLOC_CTX *mem_ctx, struct sysdb_test_ctx **ctx) } /* Connect to the conf db */ - ret = confdb_init(mem_ctx, test_ctx->ev, &test_ctx->confdb); + ret = confdb_init(test_ctx, test_ctx->ev, &test_ctx->confdb); if(ret != EOK) { fail("Could not initialize connection to the confdb"); talloc_free(test_ctx); @@ -74,47 +76,278 @@ static int setup_sysdb_tests(TALLOC_CTX *mem_ctx, struct sysdb_test_ctx **ctx) return EOK; } -START_TEST (test_sysdb_store_group_posix) +START_TEST (test_sysdb_store_local_account_posix) { int ret; struct sysdb_test_ctx *test_ctx; - TALLOC_CTX *mem_ctx; /* Setup */ - mem_ctx = talloc_new(NULL); - ret = setup_sysdb_tests(mem_ctx, &test_ctx); + ret = setup_sysdb_tests(&test_ctx); if (ret != EOK) { fail("Could not set up the test"); return; } - ret = sysdb_store_group_posix(test_ctx, test_ctx->sysdb, - "LOCAL", "sysdbtestgroup", 67000); - fail_if(ret != EOK, "Could not store sysdbtestgroup"); + /* Store a user account with username, password, + * uid, gid, gecos, homedir and shell + */ + const char *username = talloc_asprintf(test_ctx, "testuser%d", _i); + const char *home = talloc_asprintf(test_ctx, "/home/testuser%d", _i); + + ret = sysdb_store_account_posix(test_ctx, test_ctx->sysdb, + "LOCAL", username, "password", + _i, _i, + "Test User", + home, + "/bin/bash"); + fail_if(ret != EOK, "Could not store POSIX user %s", username); - talloc_free(mem_ctx); + talloc_free(test_ctx); } END_TEST -START_TEST (test_sysdb_replace_group_posix) +START_TEST (test_sysdb_store_local_group_posix) { int ret; struct sysdb_test_ctx *test_ctx; - TALLOC_CTX *mem_ctx; /* Setup */ - mem_ctx = talloc_new(NULL); - ret = setup_sysdb_tests(mem_ctx, &test_ctx); + ret = setup_sysdb_tests(&test_ctx); if (ret != EOK) { fail("Could not set up the test"); return; } ret = sysdb_store_group_posix(test_ctx, test_ctx->sysdb, - "LOCAL", "sysdbtestgroup", 67001); - fail_if(ret != EOK, "Could not store sysdbtestgroup"); + "LOCAL", SYSDB_POSIX_TEST_GROUP, _i); + fail_if(ret != EOK, "Could not store POSIX group"); + + talloc_free(test_ctx); +} +END_TEST + +START_TEST (test_sysdb_get_local_group_posix) +{ + int ret; + struct sysdb_test_ctx *test_ctx; + struct ldb_result *res; + struct ldb_dn *base_group_dn; + const char *attrs[] = { SYSDB_GR_NAME, SYSDB_GR_GIDNUM, NULL }; + const char *name; + gid_t test_gid; + + /* Setup */ + ret = setup_sysdb_tests(&test_ctx); + if (ret != EOK) { + fail("Could not set up the test"); + return; + } + + /* Set up the base DN */ + base_group_dn = ldb_dn_new_fmt(test_ctx, test_ctx->sysdb->ldb, + SYSDB_TMPL_GROUP_BASE, "LOCAL"); + if (base_group_dn == NULL) { + fail("Could not create basedn for LOCAL groups"); + return; + } + + /* Look up the group by gid */ + ret = ldb_search(test_ctx->sysdb->ldb, test_ctx, + &res, base_group_dn, LDB_SCOPE_ONELEVEL, + attrs, SYSDB_GRGID_FILTER, (unsigned long)_i); + if (ret != LDB_SUCCESS) { + fail("Could not locate group %d", _i); + return; + } + + if (res->count < 1) { + fail("Local group %d doesn't exist.\n", _i); + return; + } + else if (res->count > 1) { + fail("More than one group shared gid %d", _i); + return; + } + + name = ldb_msg_find_attr_as_string(res->msgs[0], SYSDB_GR_NAME, NULL); + fail_unless(strcmp(name, SYSDB_POSIX_TEST_GROUP) == 0, + "Returned group name was %s, expecting %s", + name, SYSDB_POSIX_TEST_GROUP); + talloc_free(res); + + /* Look up the group by name */ + ret = ldb_search(test_ctx->sysdb->ldb, test_ctx, + &res, base_group_dn, LDB_SCOPE_ONELEVEL, + attrs, SYSDB_GRNAM_FILTER, SYSDB_POSIX_TEST_GROUP); + if (ret != LDB_SUCCESS) { + fail("Could not locate group %d", _i); + return; + } + + if (res->count < 1) { + fail("Local group %s doesn't exist.", SYSDB_POSIX_TEST_GROUP); + return; + } + else if (res->count > 1) { + fail("More than one group shared name %s", SYSDB_POSIX_TEST_GROUP); + return; + } + + test_gid = ldb_msg_find_attr_as_uint64(res->msgs[0], SYSDB_GR_GIDNUM, 0); + fail_unless(test_gid == _i, + "Returned group id was %lu, expecting %lu", + test_gid, _i); + + talloc_free(test_ctx); +} +END_TEST + +START_TEST (test_sysdb_add_acct_to_posix_group) +{ + int ret; + struct sysdb_test_ctx *test_ctx; + char *username; + + /* Setup */ + ret = setup_sysdb_tests(&test_ctx); + if (ret != EOK) { + fail("Could not set up the test"); + return; + } + + /* Add user to test group */ + username = talloc_asprintf(test_ctx, "testuser%d", _i); + ret = sysdb_add_acct_to_posix_group(test_ctx, + test_ctx->sysdb, + "LOCAL", + SYSDB_POSIX_TEST_GROUP, + username); + fail_if(ret != EOK, + "Failed to add user %s to group %s. Error was: %d", + username, SYSDB_POSIX_TEST_GROUP, ret); - talloc_free(mem_ctx); + talloc_free(test_ctx); +} +END_TEST + +START_TEST (test_sysdb_verify_posix_group_members) +{ + char found_group, found_user; + int ret, i; + struct sysdb_test_ctx *test_ctx; + char *username; + char *member; + char *group; + struct ldb_dn *group_dn; + struct ldb_dn *user_dn; + struct ldb_result *res; + struct ldb_message_element *el; + const char *group_attrs[] = { SYSDB_GR_MEMBER, NULL }; + const char *user_attrs[] = { SYSDB_PW_MEMBEROF, NULL }; + + /* Setup */ + ret = setup_sysdb_tests(&test_ctx); + if (ret != EOK) { + fail("Could not set up the test"); + return; + } + + username = talloc_asprintf(test_ctx, "testuser%d", _i); + fail_if (username == NULL, "Could not allocate username"); + + member = talloc_asprintf(test_ctx, + SYSDB_PW_NAME"=%s,"SYSDB_TMPL_USER_BASE, + username, "LOCAL"); + fail_if(member == NULL, "Could not allocate member dn"); + + user_dn = ldb_dn_new_fmt(test_ctx, test_ctx->sysdb->ldb, member); + fail_if(user_dn == NULL, "Could not create user_dn object"); + + group = talloc_asprintf(test_ctx, + SYSDB_GR_NAME"=%s,"SYSDB_TMPL_GROUP_BASE, + SYSDB_POSIX_TEST_GROUP, "LOCAL"); + fail_if(group == NULL, "Could not allocate group dn"); + + group_dn = ldb_dn_new_fmt(test_ctx, test_ctx->sysdb->ldb, group); + fail_if(group_dn == NULL, "Could not create group_dn object"); + + /* Look up the group by name */ + ret = ldb_search(test_ctx->sysdb->ldb, test_ctx, + &res, group_dn, LDB_SCOPE_BASE, + group_attrs, SYSDB_GRNAM_FILTER, SYSDB_POSIX_TEST_GROUP); + if (ret != LDB_SUCCESS) { + fail("Could not locate group %d", _i); + return; + } + + if (res->count < 1) { + fail("Local group %s doesn't exist.", SYSDB_POSIX_TEST_GROUP); + return; + } + else if (res->count > 1) { + fail("More than one group shared name %s", SYSDB_POSIX_TEST_GROUP); + return; + } + + /* Check the members for the requested user */ + found_group = i = 0; + el = ldb_msg_find_element(res->msgs[0], SYSDB_GR_MEMBER); + if (el && el->num_values > 0) { + while (i < el->num_values && !found_group) { + struct ldb_val v = el->values[i]; + char *value = talloc_strndup(test_ctx, (char *)v.data, v.length); + if (strcmp(value, member) == 0) { + found_group = 1; + } + talloc_free(value); + i++; + } + } + else { + fail("No member attributes for group %s", SYSDB_POSIX_TEST_GROUP); + } + + fail_unless(found_group == 1, "%s does not have %s as a member", SYSDB_POSIX_TEST_GROUP, username); + + /* Look up the user by name */ + ret = ldb_search(test_ctx->sysdb->ldb, test_ctx, + &res, user_dn, LDB_SCOPE_BASE, + user_attrs, SYSDB_PWNAM_FILTER, username); + if (ret != LDB_SUCCESS) { + fail("Could not locate user %s", username); + return; + } + + if (res->count < 1) { + fail("Local user %s doesn't exist.", username); + return; + } + else if (res->count > 1) { + fail("More than one user shared name %s", username); + return; + } + + /* Check that the user is a member of the SYSDB_POSIX_TEST_GROUP */ + found_user = i = 0; + el = ldb_msg_find_element(res->msgs[0], SYSDB_PW_MEMBEROF); + if (el && el->num_values > 0) { + while (i < el->num_values && !found_user) { + struct ldb_val v = el->values[i]; + char *value = talloc_strndup(test_ctx, (char *)v.data, v.length); + if (strcmp(value, group) == 0) { + found_user = 1; + } + talloc_free(value); + i++; + } + } + else { + fail("No memberOf attributes for user %s", username); + } + + fail_unless(found_group, "User %s not a memberOf group %s", username, SYSDB_POSIX_TEST_GROUP); + + talloc_free(test_ctx); } END_TEST @@ -122,10 +355,35 @@ Suite *create_sysdb_suite(void) { Suite *s = suite_create("sysdb"); - /* POSIX Group test case */ +/* POSIX User test case */ + TCase *tc_posix_users = tcase_create("\tPOSIX Users"); + + /* Create a new user */ + tcase_add_loop_test(tc_posix_users, test_sysdb_store_local_account_posix,26000,26010); + +/* POSIX Group test case */ TCase *tc_posix_gr = tcase_create("\tPOSIX Groups"); - tcase_add_test(tc_posix_gr, test_sysdb_store_group_posix); - tcase_add_test(tc_posix_gr, test_sysdb_replace_group_posix); + + /* Create a new group */ + tcase_add_loop_test(tc_posix_gr, test_sysdb_store_local_group_posix,27000,27001); + + /* Verify that the new group exists */ + tcase_add_loop_test(tc_posix_gr, test_sysdb_get_local_group_posix,27000,27001); + + /* Change the gid of the group we created */ + tcase_add_loop_test(tc_posix_gr, test_sysdb_store_local_group_posix,27001,27002); + + /* Verify that the group has been changed */ + tcase_add_loop_test(tc_posix_gr, test_sysdb_get_local_group_posix,27001,27002); + + /* Add users to the group */ + tcase_add_loop_test(tc_posix_gr, test_sysdb_add_acct_to_posix_group, 26000, 26010); + + /* Verify member and memberOf */ + tcase_add_loop_test(tc_posix_gr, test_sysdb_verify_posix_group_members, 26000, 26010); + +/* Add all test cases to the test suite */ + suite_add_tcase(s, tc_posix_users); suite_add_tcase(s, tc_posix_gr); return s; |