summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJakub Hrozek <jhrozek@redhat.com>2010-09-20 11:52:27 -0400
committerStephen Gallagher <sgallagh@redhat.com>2010-10-08 19:26:55 -0400
commitb302ec4cad436c8025675f74486e5d5f95730a20 (patch)
tree6e5b43bde1ddeda6f777e57c8de2fa9f5887b54d
parent4c5c160e6461144be85e2cd32b46ff20cb7ff945 (diff)
downloadsssd-b302ec4cad436c8025675f74486e5d5f95730a20.tar.gz
sssd-b302ec4cad436c8025675f74486e5d5f95730a20.tar.xz
sssd-b302ec4cad436c8025675f74486e5d5f95730a20.zip
sysdb interface for adding incomplete group entries
Useful for optimizing the initgroups operation.
-rw-r--r--src/db/sysdb.h8
-rw-r--r--src/db/sysdb_ops.c175
-rw-r--r--src/tests/sysdb-tests.c72
3 files changed, 255 insertions, 0 deletions
diff --git a/src/db/sysdb.h b/src/db/sysdb.h
index 04ce49e66..cb3d4238e 100644
--- a/src/db/sysdb.h
+++ b/src/db/sysdb.h
@@ -483,6 +483,14 @@ struct tevent_req *sysdb_add_group_send(TALLOC_CTX *mem_ctx,
int cache_timeout);
int sysdb_add_group_recv(struct tevent_req *req);
+/* Add a incomplete, expired group */
+struct tevent_req *sysdb_add_incomplete_group_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ const char *name, gid_t gid);
+int sysdb_add_incomplete_group_recv(struct tevent_req *req);
+
/* mod_op must be either LDB_FLAG_MOD_ADD or LDB_FLAG_MOD_DELETE */
struct tevent_req *sysdb_mod_group_member_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
diff --git a/src/db/sysdb_ops.c b/src/db/sysdb_ops.c
index 7ab53e17d..e5219cded 100644
--- a/src/db/sysdb_ops.c
+++ b/src/db/sysdb_ops.c
@@ -2448,6 +2448,181 @@ int sysdb_add_group_recv(struct tevent_req *req)
}
+/* =Add-A-Incomplete-Group====================================================== */
+
+struct sysdb_add_incomplete_group_state {
+ struct tevent_context *ev;
+ struct sysdb_handle *handle;
+ struct sss_domain_info *domain;
+
+ const char *name;
+ gid_t gid;
+};
+
+static void sysdb_add_incomplete_group_user_check(struct tevent_req *subreq);
+static void sysdb_add_incomplete_group_basic_done(struct tevent_req *subreq);
+static void sysdb_add_incomplete_group_set_attrs_done(struct tevent_req *subreq);
+
+struct tevent_req *sysdb_add_incomplete_group_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct sysdb_handle *handle,
+ struct sss_domain_info *domain,
+ const char *name, gid_t gid)
+{
+ struct tevent_req *req, *subreq;
+ struct sysdb_add_incomplete_group_state *state;
+ int ret;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct sysdb_add_incomplete_group_state);
+ if (!req) return NULL;
+
+ state->ev = ev;
+ state->handle = handle;
+ state->domain = domain;
+ state->name = name;
+ state->gid = gid;
+
+ if (handle->ctx->mpg) {
+ /* In MPG domains you can't have groups with the same name as users,
+ * search if a user with the same name exists.
+ * Don't worry about groups, if we try to add a group with the same
+ * name the operation will fail */
+
+ subreq = sysdb_search_user_by_name_send(state, ev, NULL, handle,
+ domain, name, NULL);
+ if (!subreq) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
+ tevent_req_set_callback(subreq, sysdb_add_incomplete_group_user_check, req);
+ return req;
+ }
+
+ /* try to add the group */
+ subreq = sysdb_add_basic_group_send(state, ev, handle,
+ domain, name, gid);
+ if (!subreq) {
+ ERROR_OUT(ret, ENOMEM, fail);
+ }
+ tevent_req_set_callback(subreq, sysdb_add_incomplete_group_basic_done, req);
+ return req;
+
+fail:
+ DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
+ tevent_req_error(req, ret);
+ tevent_req_post(req, ev);
+ return req;
+}
+
+static void sysdb_add_incomplete_group_user_check(struct tevent_req *subreq)
+{
+
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct sysdb_add_incomplete_group_state *state = tevent_req_data(req,
+ struct sysdb_add_incomplete_group_state);
+ struct ldb_message *msg;
+ int ret;
+
+ /* We can succeed only if we get an ENOENT error, which means no users
+ * with the same name exist.
+ * If any other error is returned fail as well. */
+ ret = sysdb_search_user_recv(subreq, state, &msg);
+ talloc_zfree(subreq);
+ if (ret != ENOENT) {
+ if (ret == EOK) ret = EEXIST;
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ /* try to add the group */
+ subreq = sysdb_add_basic_group_send(state, state->ev,
+ state->handle, state->domain,
+ state->name, state->gid);
+ if (!subreq) {
+ DEBUG(6, ("Error: Out of memory\n"));
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ tevent_req_set_callback(subreq, sysdb_add_incomplete_group_basic_done, req);
+}
+
+static void sysdb_add_incomplete_group_basic_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ struct sysdb_add_incomplete_group_state *state = tevent_req_data(req,
+ struct sysdb_add_incomplete_group_state);
+ int ret;
+ struct sysdb_attrs *attrs;
+ time_t now;
+
+ ret = sysdb_add_basic_group_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ attrs = sysdb_new_attrs(state);
+ if (!attrs) {
+ DEBUG(6, ("Error: Out of memory\n"));
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+
+ now = time(NULL);
+
+ ret = sysdb_attrs_add_time_t(attrs, SYSDB_LAST_UPDATE, now);
+ if (ret) {
+ DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ ret = sysdb_attrs_add_time_t(attrs, SYSDB_CACHE_EXPIRE,
+ now-1);
+ if (ret) {
+ DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ subreq = sysdb_set_group_attr_send(state, state->ev,
+ state->handle, state->domain,
+ state->name, attrs,
+ SYSDB_MOD_REP);
+ if (!subreq) {
+ DEBUG(6, ("Error: Out of memory\n"));
+ tevent_req_error(req, ENOMEM);
+ return;
+ }
+ tevent_req_set_callback(subreq, sysdb_add_incomplete_group_set_attrs_done, req);
+}
+
+static void sysdb_add_incomplete_group_set_attrs_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ int ret;
+
+ ret = sysdb_set_group_attr_recv(subreq);
+ talloc_zfree(subreq);
+ if (ret) {
+ DEBUG(6, ("Error: %d (%s)\n", ret, strerror(ret)));
+ tevent_req_error(req, ret);
+ return;
+ }
+
+ tevent_req_done(req);
+}
+
+int sysdb_add_incomplete_group_recv(struct tevent_req *req)
+{
+ return sysdb_op_default_recv(req);
+}
+
/* =Add-Or-Remove-Group-Memeber=========================================== */
/* mod_op must be either SYSDB_MOD_ADD or SYSDB_MOD_DEL */
diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c
index 5bdc00547..d4d031b98 100644
--- a/src/tests/sysdb-tests.c
+++ b/src/tests/sysdb-tests.c
@@ -511,6 +511,39 @@ static void test_store_group_done(struct tevent_req *subreq)
return test_return(data, ret);
}
+static void test_add_incomplete_group_done(struct tevent_req *subreq);
+
+static void test_add_incomplete_group(struct tevent_req *req)
+{
+ struct test_data *data = tevent_req_callback_data(req, struct test_data);
+ struct tevent_req *subreq;
+ int ret;
+
+ ret = sysdb_transaction_recv(req, data, &data->handle);
+ if (ret != EOK) {
+ return test_return(data, ret);
+ }
+
+ subreq = sysdb_add_incomplete_group_send(data, data->ev, data->handle,
+ data->ctx->domain, data->groupname,
+ data->gid);
+ if (!subreq) {
+ test_return(data, ret);
+ }
+ tevent_req_set_callback(subreq, test_add_incomplete_group_done, data);
+}
+
+static void test_add_incomplete_group_done(struct tevent_req *subreq)
+{
+ struct test_data *data = tevent_req_callback_data(subreq, struct test_data);
+ int ret;
+
+ ret = sysdb_add_group_recv(subreq);
+ talloc_zfree(subreq);
+
+ return test_return(data, ret);
+}
+
static void test_remove_group_done(struct tevent_req *subreq);
static void test_remove_group(struct tevent_req *req)
@@ -1179,6 +1212,41 @@ START_TEST (test_sysdb_store_group)
}
END_TEST
+START_TEST (test_sysdb_add_incomplete_group)
+{
+ struct sysdb_test_ctx *test_ctx;
+ struct test_data *data;
+ struct tevent_req *req;
+ int ret;
+
+ /* Setup */
+ ret = setup_sysdb_tests(&test_ctx);
+ if (ret != EOK) {
+ fail("Could not set up the test");
+ return;
+ }
+
+ data = talloc_zero(test_ctx, struct test_data);
+ data->ctx = test_ctx;
+ data->ev = test_ctx->ev;
+ data->gid = _i;
+ data->groupname = talloc_asprintf(data, "testgroup%d", _i);
+
+ req = sysdb_transaction_send(data, data->ev, test_ctx->sysdb);
+ if (!req) {
+ ret = ENOMEM;
+ }
+
+ if (ret == EOK) {
+ tevent_req_set_callback(req, test_add_incomplete_group, data);
+ ret = test_loop(data);
+ }
+
+ fail_if(ret != EOK, "Could not store incomplete group #%d", _i);
+ talloc_free(test_ctx);
+}
+END_TEST
+
START_TEST (test_sysdb_remove_local_user)
{
struct sysdb_test_ctx *test_ctx;
@@ -3372,6 +3440,10 @@ Suite *create_sysdb_suite(void)
/* Create a new group */
tcase_add_loop_test(tc_sysdb, test_sysdb_store_group, 28010, 28020);
+ /* Create and remove a incomplete group */
+ tcase_add_loop_test(tc_sysdb, test_sysdb_add_incomplete_group, 28020, 28030);
+ tcase_add_loop_test(tc_sysdb, test_sysdb_remove_local_group, 28020, 28030);
+
/* Verify the groups were added */
/* Verify the groups can be queried by GID */