[SSSD] [PATCH] MEMBEROF: Implement the modify operation for ghost users
Jakub Hrozek
jhrozek at redhat.com
Tue Nov 27 16:57:28 UTC 2012
The first three patches are just refactoring. The last patch implements
the real modify operation along with a number of unit tests.
-------------- next part --------------
>From 71902d3eab67a14ba200908b7c708d3f661e4ed8 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Mon, 26 Nov 2012 13:18:59 +0100
Subject: [PATCH 1/4] MEMBEROF: split processing the member modify into a
separate function
This will allow to process ghost users in a similar fashion
---
src/ldb_modules/memberof.c | 117 +++++++++++++++++++++++++++------------------
1 file changed, 70 insertions(+), 47 deletions(-)
diff --git a/src/ldb_modules/memberof.c b/src/ldb_modules/memberof.c
index 3455b8805c85e44caab3e5833c0dddcc62bcc598..65b1fa6b9081aef2b518c741102ce59483c4209e 100644
--- a/src/ldb_modules/memberof.c
+++ b/src/ldb_modules/memberof.c
@@ -149,7 +149,8 @@ struct mbof_mod_ctx {
const struct ldb_message_element *membel;
struct ldb_message *entry;
- struct mbof_dn_array *to_add;
+ struct mbof_dn_array *mb_add;
+ struct mbof_dn_array *mb_remove;
struct ldb_message *msg;
bool terminate;
@@ -2262,7 +2263,7 @@ static int mbof_del_progeny(struct mbof_del_operation *delop)
/* see if there are follow functions to run */
if (del_ctx->follow_mod) {
return mbof_mod_add(del_ctx->follow_mod,
- del_ctx->follow_mod->to_add);
+ del_ctx->follow_mod->mb_add);
}
/* ok, no more ops, this means our job is done */
@@ -2533,7 +2534,7 @@ static int mbof_del_muop_callback(struct ldb_request *req,
/* see if there are follow functions to run */
else if (del_ctx->follow_mod) {
return mbof_mod_add(del_ctx->follow_mod,
- del_ctx->follow_mod->to_add);
+ del_ctx->follow_mod->mb_add);
}
else {
return ldb_module_done(ctx->req,
@@ -2645,7 +2646,7 @@ static int mbof_del_ghop_callback(struct ldb_request *req,
/* see if there are follow functions to run */
else if (del_ctx->follow_mod) {
return mbof_mod_add(del_ctx->follow_mod,
- del_ctx->follow_mod->to_add);
+ del_ctx->follow_mod->mb_add);
}
else {
return ldb_module_done(ctx->req,
@@ -2693,6 +2694,11 @@ static int mbof_orig_mod(struct mbof_mod_ctx *mod_ctx);
static int mbof_orig_mod_callback(struct ldb_request *req,
struct ldb_reply *ares);
static int mbof_mod_process(struct mbof_mod_ctx *mod_ctx, bool *done);
+static int mbof_mod_process_membel(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
+ struct ldb_message *entry,
+ const struct ldb_message_element *membel,
+ struct mbof_dn_array **_added,
+ struct mbof_dn_array **_removed);
static int mbof_mod_delete(struct mbof_mod_ctx *mod_ctx,
struct mbof_dn_array *del);
static int mbof_fill_dn_array(TALLOC_CTX *memctx,
@@ -2916,63 +2922,96 @@ static int mbof_orig_mod_callback(struct ldb_request *req,
static int mbof_mod_process(struct mbof_mod_ctx *mod_ctx, bool *done)
{
- const struct ldb_message_element *el;
struct ldb_context *ldb;
struct mbof_ctx *ctx;
- struct mbof_dn_array *removed;
- struct mbof_dn_array *added;
- int i, j, ret;
+ int ret;
ctx = mod_ctx->ctx;
ldb = ldb_module_get_ctx(ctx->module);
- switch (mod_ctx->membel->flags) {
+ ret = mbof_mod_process_membel(mod_ctx, ldb, mod_ctx->entry, mod_ctx->membel,
+ &mod_ctx->mb_add, &mod_ctx->mb_remove);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ /* Process the operations */
+ if (mod_ctx->mb_remove && mod_ctx->mb_remove->num) {
+ return mbof_mod_delete(mod_ctx, mod_ctx->mb_remove);
+ }
+
+ if (mod_ctx->mb_add && mod_ctx->mb_add->num) {
+ return mbof_mod_add(mod_ctx, mod_ctx->mb_add);
+ }
+
+ /* the replacement function resulted in a null op,
+ * nothing to do, return happily */
+ *done = true;
+ return LDB_SUCCESS;
+}
+
+static int mbof_mod_process_membel(TALLOC_CTX *mem_ctx,
+ struct ldb_context *ldb,
+ struct ldb_message *entry,
+ const struct ldb_message_element *membel,
+ struct mbof_dn_array **_added,
+ struct mbof_dn_array **_removed)
+{
+ const struct ldb_message_element *el;
+ struct mbof_dn_array *removed = NULL;
+ struct mbof_dn_array *added = NULL;
+ int i, j, ret;
+
+ if (!membel) {
+ /* Nothing to do.. */
+ return LDB_SUCCESS;
+ }
+
+ switch (membel->flags) {
case LDB_FLAG_MOD_ADD:
- ret = mbof_fill_dn_array(mod_ctx, ldb, mod_ctx->membel, &added);
+ ret = mbof_fill_dn_array(mem_ctx, ldb, membel, &added);
if (ret != LDB_SUCCESS) {
return ret;
}
-
- return mbof_mod_add(mod_ctx, added);
+ break;
case LDB_FLAG_MOD_DELETE:
- if (mod_ctx->membel->num_values == 0) {
- el = ldb_msg_find_element(mod_ctx->entry, DB_MEMBER);
+ if (membel->num_values == 0) {
+ el = ldb_msg_find_element(entry, DB_MEMBER);
} else {
- el = mod_ctx->membel;
+ el = membel;
}
if (!el) {
/* nothing to do really */
- *done = true;
- return LDB_SUCCESS;
+ break;
}
- ret = mbof_fill_dn_array(mod_ctx, ldb, el, &removed);
+ ret = mbof_fill_dn_array(mem_ctx, ldb, el, &removed);
if (ret != LDB_SUCCESS) {
return ret;
}
-
- return mbof_mod_delete(mod_ctx, removed);
+ break;
case LDB_FLAG_MOD_REPLACE:
removed = NULL;
- el = ldb_msg_find_element(mod_ctx->entry, DB_MEMBER);
+ el = ldb_msg_find_element(entry, DB_MEMBER);
if (el) {
- ret = mbof_fill_dn_array(mod_ctx, ldb, el, &removed);
+ ret = mbof_fill_dn_array(mem_ctx, ldb, el, &removed);
if (ret != LDB_SUCCESS) {
return ret;
}
}
added = NULL;
- el = mod_ctx->membel;
+ el = membel;
if (el) {
- ret = mbof_fill_dn_array(mod_ctx, ldb, el, &added);
+ ret = mbof_fill_dn_array(mem_ctx, ldb, el, &added);
if (ret != LDB_SUCCESS) {
+ talloc_free(removed);
return ret;
}
}
@@ -2999,31 +3038,15 @@ static int mbof_mod_process(struct mbof_mod_ctx *mod_ctx, bool *done)
}
}
}
+ break;
- /* if we need to add something put it away so that it
- * can be done after all delete operations are over */
- if (added && added->num) {
- mod_ctx->to_add = added;
- }
-
- /* if we have something to remove do it first */
- if (removed && removed->num) {
- return mbof_mod_delete(mod_ctx, removed);
- }
-
- /* if there is nothing to remove and we have stuff to add
- * do it right away */
- if (mod_ctx->to_add) {
- return mbof_mod_add(mod_ctx, added);
- }
-
- /* the replacement function resulted in a null op,
- * nothing to do, return happily */
- *done = true;
- return LDB_SUCCESS;
+ default:
+ return LDB_ERR_OPERATIONS_ERROR;
}
- return LDB_ERR_OPERATIONS_ERROR;
+ *_added = added;
+ *_removed = removed;
+ return LDB_SUCCESS;
}
static int mbof_mod_add(struct mbof_mod_ctx *mod_ctx,
@@ -3111,7 +3134,7 @@ static int mbof_mod_delete(struct mbof_mod_ctx *mod_ctx,
}
/* add followup function if we also have stuff to add */
- if (mod_ctx->to_add) {
+ if (mod_ctx->mb_add) {
del_ctx->follow_mod = mod_ctx;
}
--
1.8.0
-------------- next part --------------
>From a6a1f85fd581ddf31fc3379048e227327634602f Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Mon, 26 Nov 2012 18:22:12 +0100
Subject: [PATCH 2/4] MEMBEROF: Split the del ghost attribute op into a
reusable function
This new function is going to be reused by the modify operation
---
src/ldb_modules/memberof.c | 34 ++++++++++++++++++++++------------
1 file changed, 22 insertions(+), 12 deletions(-)
diff --git a/src/ldb_modules/memberof.c b/src/ldb_modules/memberof.c
index 65b1fa6b9081aef2b518c741102ce59483c4209e..211b8ac09e13a8aaece0b306bf00c8d2fc666233 100644
--- a/src/ldb_modules/memberof.c
+++ b/src/ldb_modules/memberof.c
@@ -2388,11 +2388,12 @@ static int mbof_del_fill_muop(struct mbof_del_ctx *del_ctx,
return LDB_SUCCESS;
}
-static int mbof_del_fill_ghop(struct mbof_del_ctx *del_ctx,
- struct ldb_message *entry)
+static int mbof_del_fill_ghop_ex(struct mbof_del_ctx *del_ctx,
+ struct ldb_message *entry,
+ struct ldb_val *ghvals,
+ unsigned int num_gh_vals)
{
struct ldb_message_element *mbof;
- struct ldb_message_element *ghel;
struct ldb_dn *valdn;
int ret;
int i, j;
@@ -2403,12 +2404,6 @@ static int mbof_del_fill_ghop(struct mbof_del_ctx *del_ctx,
return LDB_SUCCESS;
}
- ghel = ldb_msg_find_element(entry, DB_GHOST);
- if (ghel == NULL || ghel->num_values == 0) {
- /* No ghel attribute, just return success */
- return LDB_SUCCESS;
- }
-
ret = entry_is_group_object(entry);
switch (ret) {
case LDB_SUCCESS:
@@ -2427,7 +2422,7 @@ static int mbof_del_fill_ghop(struct mbof_del_ctx *del_ctx,
ldb_debug(ldb_module_get_ctx(del_ctx->ctx->module),
LDB_DEBUG_TRACE,
"will delete %d ghost users from %d parents\n",
- ghel->num_values, mbof->num_values);
+ num_gh_vals, mbof->num_values);
for (i = 0; i < mbof->num_values; i++) {
valdn = ldb_dn_from_ldb_val(del_ctx->ghops,
@@ -2445,12 +2440,12 @@ static int mbof_del_fill_ghop(struct mbof_del_ctx *del_ctx,
"processing ghosts in parent [%s]\n",
(const char *) mbof->values[i].data);
- for (j = 0; j < ghel->num_values; j++) {
+ for (j = 0; j < num_gh_vals; j++) {
ret = mbof_append_muop(del_ctx, &del_ctx->ghops,
&del_ctx->num_ghops,
LDB_FLAG_MOD_DELETE,
valdn,
- (const char *) ghel->values[j].data,
+ (const char *) ghvals[j].data,
DB_GHOST);
if (ret != LDB_SUCCESS) {
return ret;
@@ -2461,6 +2456,21 @@ static int mbof_del_fill_ghop(struct mbof_del_ctx *del_ctx,
return LDB_SUCCESS;
}
+static int mbof_del_fill_ghop(struct mbof_del_ctx *del_ctx,
+ struct ldb_message *entry)
+{
+ struct ldb_message_element *ghel;
+
+ ghel = ldb_msg_find_element(entry, DB_GHOST);
+ if (ghel == NULL || ghel->num_values == 0) {
+ /* No ghel attribute, just return success */
+ return LDB_SUCCESS;
+ }
+
+ return mbof_del_fill_ghop_ex(del_ctx, entry,
+ ghel->values, ghel->num_values);
+}
+
/* del memberuid attributes from parent groups */
static int mbof_del_muop(struct mbof_del_ctx *del_ctx)
{
--
1.8.0
-------------- next part --------------
>From 11f7c828d4d9dd5ba9673d6832d614a81c12f51c Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Tue, 27 Nov 2012 16:06:42 +0100
Subject: [PATCH 3/4] MEMBEROF: Split the add ghost operation into a separate
function
This new function will be reused by the modify operation later
---
src/ldb_modules/memberof.c | 90 +++++++++++++++++++++++++++++++++++++---------
1 file changed, 73 insertions(+), 17 deletions(-)
diff --git a/src/ldb_modules/memberof.c b/src/ldb_modules/memberof.c
index 211b8ac09e13a8aaece0b306bf00c8d2fc666233..2504da526d6e5ba76159de69e43db37dced88526 100644
--- a/src/ldb_modules/memberof.c
+++ b/src/ldb_modules/memberof.c
@@ -353,6 +353,57 @@ static int mbof_append_addop(struct mbof_add_ctx *add_ctx,
return LDB_SUCCESS;
}
+static int mbof_add_fill_ghop_ex(struct mbof_add_ctx *add_ctx,
+ struct ldb_message *entry,
+ struct mbof_dn_array *parents,
+ struct ldb_val *ghvals,
+ unsigned int num_gh_vals)
+{
+ int ret;
+ int i, j;
+
+ if (!parents || parents->num == 0) {
+ /* no parents attributes ... */
+ return LDB_SUCCESS;
+ }
+
+ ret = entry_is_group_object(entry);
+ switch (ret) {
+ case LDB_SUCCESS:
+ /* it's a group object, continue */
+ break;
+
+ case LDB_ERR_NO_SUCH_ATTRIBUTE:
+ /* it is not a group object, just return */
+ return LDB_SUCCESS;
+
+ default:
+ /* an error occured, return */
+ return ret;
+ }
+
+ ldb_debug(ldb_module_get_ctx(add_ctx->ctx->module),
+ LDB_DEBUG_TRACE,
+ "will add %d ghost users to %d parents\n",
+ num_gh_vals, parents->num);
+
+ for (i = 0; i < parents->num; i++) {
+ for (j = 0; j < num_gh_vals; j++) {
+ ret = mbof_append_muop(add_ctx, &add_ctx->muops,
+ &add_ctx->num_muops,
+ LDB_FLAG_MOD_ADD,
+ parents->dns[i],
+ (const char *) ghvals[j].data,
+ DB_GHOST);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ }
+ }
+
+ return LDB_SUCCESS;
+}
+
static int memberof_recompute_task(struct ldb_module *module,
struct ldb_request *req);
@@ -362,6 +413,9 @@ static int mbof_next_add(struct mbof_add_operation *addop);
static int mbof_next_add_callback(struct ldb_request *req,
struct ldb_reply *ares);
static int mbof_add_operation(struct mbof_add_operation *addop);
+static int mbof_add_fill_ghop(struct mbof_add_ctx *add_ctx,
+ struct ldb_message *entry,
+ struct mbof_dn_array *parents);
static int mbof_add_missing(struct mbof_add_ctx *add_ctx, struct ldb_dn *dn);
static int mbof_add_cleanup(struct mbof_add_ctx *add_ctx);
static int mbof_add_cleanup_callback(struct ldb_request *req,
@@ -828,23 +882,9 @@ static int mbof_add_operation(struct mbof_add_operation *addop)
return ret;
}
- el = ldb_msg_find_element(addop->entry, DB_GHOST);
- if (el) {
- for (i = 0; i < el->num_values; i++) {
- /* add ghost to all group's parents */
- for (j = 0; j < parents->num; j++) {
- ret = mbof_append_muop(add_ctx, &add_ctx->muops,
- &add_ctx->num_muops,
- LDB_FLAG_MOD_ADD,
- parents->dns[j],
- (char *)el->values[i].data,
- DB_GHOST);
- if (ret != LDB_SUCCESS) {
- return ret;
- }
- }
-
- }
+ ret = mbof_add_fill_ghop(add_ctx, addop->entry, parents);
+ if (ret != LDB_SUCCESS) {
+ return ret;
}
/* we are done with the entry now */
@@ -889,6 +929,22 @@ static int mbof_add_operation(struct mbof_add_operation *addop)
return ldb_next_request(ctx->module, mod_req);
}
+static int mbof_add_fill_ghop(struct mbof_add_ctx *add_ctx,
+ struct ldb_message *entry,
+ struct mbof_dn_array *parents)
+{
+ struct ldb_message_element *ghel;
+
+ ghel = ldb_msg_find_element(entry, DB_GHOST);
+ if (ghel == NULL || ghel->num_values == 0) {
+ /* No ghel attribute, just return success */
+ return LDB_SUCCESS;
+ }
+
+ return mbof_add_fill_ghop_ex(add_ctx, entry, parents,
+ ghel->values, ghel->num_values);
+}
+
static int mbof_add_missing(struct mbof_add_ctx *add_ctx, struct ldb_dn *dn)
{
struct mbof_dn *mdn;
--
1.8.0
-------------- next part --------------
>From cf6c11388456c115c1b9263b945715f642568315 Mon Sep 17 00:00:00 2001
From: Jakub Hrozek <jhrozek at redhat.com>
Date: Tue, 27 Nov 2012 16:09:23 +0100
Subject: [PATCH 4/4] MEMBEROF: Implement the modify operation for ghost users
---
src/ldb_modules/memberof.c | 284 ++++++++++++++++++++++----
src/tests/sysdb-tests.c | 486 ++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 724 insertions(+), 46 deletions(-)
diff --git a/src/ldb_modules/memberof.c b/src/ldb_modules/memberof.c
index 2504da526d6e5ba76159de69e43db37dced88526..90c31da4ac2a2746161dbb3c399d0b291962aab6 100644
--- a/src/ldb_modules/memberof.c
+++ b/src/ldb_modules/memberof.c
@@ -45,6 +45,11 @@
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#endif
+struct mbof_val_array {
+ struct ldb_val *vals;
+ int num;
+};
+
struct mbof_dn_array {
struct ldb_dn **dns;
int num;
@@ -147,11 +152,15 @@ struct mbof_mod_ctx {
struct mbof_ctx *ctx;
const struct ldb_message_element *membel;
+ const struct ldb_message_element *ghel;
struct ldb_message *entry;
struct mbof_dn_array *mb_add;
struct mbof_dn_array *mb_remove;
+ struct mbof_val_array *gh_add;
+ struct mbof_val_array *gh_remove;
+
struct ldb_message *msg;
bool terminate;
};
@@ -2260,7 +2269,8 @@ static int mbof_del_mod_callback(struct ldb_request *req,
}
static int mbof_mod_add(struct mbof_mod_ctx *mod_ctx,
- struct mbof_dn_array *ael);
+ struct mbof_dn_array *ael,
+ struct mbof_val_array *addgh);
static int mbof_del_progeny(struct mbof_del_operation *delop)
{
@@ -2319,7 +2329,8 @@ static int mbof_del_progeny(struct mbof_del_operation *delop)
/* see if there are follow functions to run */
if (del_ctx->follow_mod) {
return mbof_mod_add(del_ctx->follow_mod,
- del_ctx->follow_mod->mb_add);
+ del_ctx->follow_mod->mb_add,
+ del_ctx->follow_mod->gh_add);
}
/* ok, no more ops, this means our job is done */
@@ -2600,7 +2611,8 @@ static int mbof_del_muop_callback(struct ldb_request *req,
/* see if there are follow functions to run */
else if (del_ctx->follow_mod) {
return mbof_mod_add(del_ctx->follow_mod,
- del_ctx->follow_mod->mb_add);
+ del_ctx->follow_mod->mb_add,
+ del_ctx->follow_mod->gh_add);
}
else {
return ldb_module_done(ctx->req,
@@ -2712,7 +2724,8 @@ static int mbof_del_ghop_callback(struct ldb_request *req,
/* see if there are follow functions to run */
else if (del_ctx->follow_mod) {
return mbof_mod_add(del_ctx->follow_mod,
- del_ctx->follow_mod->mb_add);
+ del_ctx->follow_mod->mb_add,
+ del_ctx->follow_mod->gh_add);
}
else {
return ldb_module_done(ctx->req,
@@ -2765,19 +2778,30 @@ static int mbof_mod_process_membel(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
const struct ldb_message_element *membel,
struct mbof_dn_array **_added,
struct mbof_dn_array **_removed);
+static int mbof_mod_process_ghel(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
+ struct ldb_message *entry,
+ const struct ldb_message_element *membel,
+ struct mbof_val_array **_added,
+ struct mbof_val_array **_removed);
static int mbof_mod_delete(struct mbof_mod_ctx *mod_ctx,
- struct mbof_dn_array *del);
+ struct mbof_dn_array *del,
+ struct mbof_val_array *delgh);
static int mbof_fill_dn_array(TALLOC_CTX *memctx,
struct ldb_context *ldb,
const struct ldb_message_element *el,
struct mbof_dn_array **dn_array);
+static int mbof_fill_vals_array(TALLOC_CTX *memctx,
+ struct ldb_context *ldb,
+ const struct ldb_message_element *el,
+ struct mbof_val_array **val_array);
static int memberof_mod(struct ldb_module *module, struct ldb_request *req)
{
struct ldb_message_element *el;
struct mbof_mod_ctx *mod_ctx;
struct mbof_ctx *ctx;
- static const char *attrs[] = {DB_MEMBER, DB_MEMBEROF, NULL};
+ static const char *attrs[] = { DB_OC, DB_GHOST,
+ DB_MEMBER, DB_MEMBEROF, NULL};
struct ldb_context *ldb = ldb_module_get_ctx(module);
struct ldb_request *search;
int ret;
@@ -2820,15 +2844,15 @@ static int memberof_mod(struct ldb_module *module, struct ldb_request *req)
return LDB_ERR_OPERATIONS_ERROR;
}
- /* continue with normal ops if there are no members */
- el = ldb_msg_find_element(mod_ctx->msg, DB_MEMBER);
- if (!el) {
+ mod_ctx->membel = ldb_msg_find_element(mod_ctx->msg, DB_MEMBER);
+ mod_ctx->ghel = ldb_msg_find_element(mod_ctx->msg, DB_GHOST);
+
+ /* continue with normal ops if there are no members and no ghosts */
+ if (mod_ctx->membel == NULL && mod_ctx->ghel == NULL) {
mod_ctx->terminate = true;
return mbof_orig_mod(mod_ctx);
}
- mod_ctx->membel = el;
-
/* can't do anything,
* must check first what's on the entry */
ret = ldb_build_search_req(&search, ldb, mod_ctx,
@@ -3001,13 +3025,21 @@ static int mbof_mod_process(struct mbof_mod_ctx *mod_ctx, bool *done)
return ret;
}
+ ret = mbof_mod_process_ghel(mod_ctx, ldb, mod_ctx->entry, mod_ctx->ghel,
+ &mod_ctx->gh_add, &mod_ctx->gh_remove);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
/* Process the operations */
- if (mod_ctx->mb_remove && mod_ctx->mb_remove->num) {
- return mbof_mod_delete(mod_ctx, mod_ctx->mb_remove);
+ if ((mod_ctx->mb_remove && mod_ctx->mb_remove->num) ||
+ (mod_ctx->gh_remove && mod_ctx->gh_remove->num)) {
+ return mbof_mod_delete(mod_ctx, mod_ctx->mb_remove, mod_ctx->gh_remove);
}
- if (mod_ctx->mb_add && mod_ctx->mb_add->num) {
- return mbof_mod_add(mod_ctx, mod_ctx->mb_add);
+ if ((mod_ctx->mb_add && mod_ctx->mb_add->num) ||
+ (mod_ctx->gh_add && mod_ctx->gh_add->num)) {
+ return mbof_mod_add(mod_ctx, mod_ctx->mb_add, mod_ctx->gh_add);
}
/* the replacement function resulted in a null op,
@@ -3115,8 +3147,109 @@ static int mbof_mod_process_membel(TALLOC_CTX *mem_ctx,
return LDB_SUCCESS;
}
+static int mbof_mod_process_ghel(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
+ struct ldb_message *entry,
+ const struct ldb_message_element *ghel,
+ struct mbof_val_array **_added,
+ struct mbof_val_array **_removed)
+{
+ const struct ldb_message_element *el;
+ struct mbof_val_array *removed = NULL;
+ struct mbof_val_array *added = NULL;
+ int i, j, ret;
+
+ if (!ghel) {
+ /* Nothing to do.. */
+ return LDB_SUCCESS;
+ }
+
+ el = ldb_msg_find_element(entry, DB_MEMBEROF);
+ if (!el || el->num_values == 0) {
+ /* no memberof attributes ... */
+ return LDB_SUCCESS;
+ }
+
+ switch (ghel->flags) {
+ case LDB_FLAG_MOD_ADD:
+ ret = mbof_fill_vals_array(mem_ctx, ldb, ghel, &added);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ break;
+
+ case LDB_FLAG_MOD_DELETE:
+ if (ghel->num_values == 0) {
+ el = ldb_msg_find_element(entry, DB_GHOST);
+ } else {
+ el = ghel;
+ }
+
+ if (!el) {
+ /* nothing to do really */
+ break;
+ }
+
+ ret = mbof_fill_vals_array(mem_ctx, ldb, ghel, &removed);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ break;
+
+ case LDB_FLAG_MOD_REPLACE:
+ el = ldb_msg_find_element(entry, DB_GHOST);
+ if (el) {
+ ret = mbof_fill_vals_array(mem_ctx, ldb, el, &removed);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ }
+
+ el = ghel;
+ if (el) {
+ ret = mbof_fill_vals_array(mem_ctx, ldb, el, &added);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(removed);
+ return ret;
+ }
+ }
+
+ /* remove from arrays values that ended up unchanged */
+ if (removed && removed->num && added && added->num) {
+ for (i = 0; i < added->num; i++) {
+ for (j = 0; j < removed->num; j++) {
+ if (strcmp((const char *) added->vals[i].data,
+ (const char *) removed->vals[j].data) == 0) {
+ break;
+ }
+ }
+ if (j < removed->num) {
+ /* preexisting one, not removed, nor added */
+ for (; j+1 < removed->num; j++) {
+ removed->vals[j] = removed->vals[j+1];
+ }
+ removed->num--;
+ for (j = i; j+1 < added->num; j++) {
+ added->vals[j] = added->vals[j+1];
+ }
+ added->num--;
+ i--;
+ }
+ }
+ }
+ break;
+
+ default:
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ *_added = added;
+ *_removed = removed;
+ return LDB_SUCCESS;
+}
+
static int mbof_mod_add(struct mbof_mod_ctx *mod_ctx,
- struct mbof_dn_array *ael)
+ struct mbof_dn_array *ael,
+ struct mbof_val_array *addgh)
{
const struct ldb_message_element *el;
struct mbof_dn_array *parents;
@@ -3136,14 +3269,6 @@ static int mbof_mod_add(struct mbof_mod_ctx *mod_ctx,
return ret;
}
- parents->dns = talloc_realloc(parents, parents->dns,
- struct ldb_dn *, parents->num + 1);
- if (!parents->dns) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
- parents->dns[parents->num] = mod_ctx->entry->dn;
- parents->num++;
-
add_ctx = talloc_zero(mod_ctx, struct mbof_add_ctx);
if (!add_ctx) {
return LDB_ERR_OPERATIONS_ERROR;
@@ -3151,18 +3276,42 @@ static int mbof_mod_add(struct mbof_mod_ctx *mod_ctx,
add_ctx->ctx = ctx;
add_ctx->msg_dn = mod_ctx->msg->dn;
- for (i = 0; i < ael->num; i++) {
- ret = mbof_append_addop(add_ctx, parents, ael->dns[i]);
+ if (addgh != NULL) {
+ /* Build the memberuid add op */
+ ret = mbof_add_fill_ghop_ex(add_ctx, mod_ctx->entry,
+ parents, addgh->vals, addgh->num);
if (ret != LDB_SUCCESS) {
return ret;
}
}
- return mbof_next_add(add_ctx->add_list);
+ if (ael != NULL) {
+ /* Add itself to the list of the parents to also get the memberuid */
+ parents->dns = talloc_realloc(parents, parents->dns,
+ struct ldb_dn *, parents->num + 1);
+ if (!parents->dns) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ parents->dns[parents->num] = mod_ctx->entry->dn;
+ parents->num++;
+
+ /* Build the member-add array */
+ for (i = 0; i < ael->num; i++) {
+ ret = mbof_append_addop(add_ctx, parents, ael->dns[i]);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ }
+
+ return mbof_next_add(add_ctx->add_list);
+ }
+
+ return mbof_add_muop(add_ctx);
}
static int mbof_mod_delete(struct mbof_mod_ctx *mod_ctx,
- struct mbof_dn_array *del)
+ struct mbof_dn_array *del,
+ struct mbof_val_array *delgh)
{
struct mbof_del_operation *first;
struct mbof_del_ctx *del_ctx;
@@ -3187,25 +3336,38 @@ static int mbof_mod_delete(struct mbof_mod_ctx *mod_ctx,
}
del_ctx->first = first;
- first->del_ctx = del_ctx;
- first->entry = mod_ctx->entry;
- first->entry_dn = mod_ctx->entry->dn;
-
- /* prepare del sets */
- for (i = 0; i < del->num; i++) {
- ret = mbof_append_delop(first, del->dns[i]);
- if (ret != LDB_SUCCESS) {
- return ret;
- }
- }
-
/* add followup function if we also have stuff to add */
- if (mod_ctx->mb_add) {
+ if (mod_ctx->mb_add || mod_ctx->gh_add) {
del_ctx->follow_mod = mod_ctx;
}
- /* now that sets are built, start processing */
- return mbof_del_execute_op(first->children[0]);
+ first->del_ctx = del_ctx;
+ first->entry = mod_ctx->entry;
+ first->entry_dn = mod_ctx->entry->dn;
+
+ if (delgh != NULL) {
+ ret = mbof_del_fill_ghop_ex(del_ctx, del_ctx->first->entry,
+ delgh->vals, delgh->num);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ }
+
+ /* prepare del sets */
+ if (del != NULL) {
+ for (i = 0; i < del->num; i++) {
+ ret = mbof_append_delop(first, del->dns[i]);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ }
+
+ /* now that sets are built, start processing */
+ return mbof_del_execute_op(first->children[0]);
+ }
+
+ /* No member processing, just delete ghosts */
+ return mbof_del_ghop(del_ctx);
}
static int mbof_fill_dn_array(TALLOC_CTX *memctx,
@@ -3246,6 +3408,42 @@ static int mbof_fill_dn_array(TALLOC_CTX *memctx,
return LDB_SUCCESS;
}
+static int mbof_fill_vals_array(TALLOC_CTX *memctx,
+ struct ldb_context *ldb,
+ const struct ldb_message_element *el,
+ struct mbof_val_array **val_array)
+{
+ struct mbof_val_array *var;
+ int i;
+
+ var = talloc_zero(memctx, struct mbof_val_array);
+ if (!var) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ *val_array = var;
+
+ if (!el || el->num_values == 0) {
+ return LDB_SUCCESS;
+ }
+
+ var->vals = talloc_array(var, struct ldb_val, el->num_values);
+ if (!var->vals) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ var->num = el->num_values;
+
+ for (i = 0; i < var->num; i++) {
+ var->vals[i].length = strlen((const char *) el->values[i].data);
+ var->vals[i].data = (uint8_t *) talloc_strdup(var,
+ (const char *) el->values[i].data);
+ if (var->vals[i].data == NULL) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ }
+
+ return LDB_SUCCESS;
+}
+
/*************************
* Cleanup task routines *
diff --git a/src/tests/sysdb-tests.c b/src/tests/sysdb-tests.c
index 7b69876ff0dc3dba5168d6f3ac096526bf7ff576..94637b0eb8c0921bfc3de0a967fbc07739f4738f 100644
--- a/src/tests/sysdb-tests.c
+++ b/src/tests/sysdb-tests.c
@@ -1996,6 +1996,190 @@ START_TEST (test_sysdb_memberof_store_group_with_ghosts)
}
END_TEST
+
+START_TEST (test_sysdb_memberof_mod_add)
+{
+ struct sysdb_test_ctx *test_ctx;
+ struct test_data *data;
+ char *ghostname;
+ int ret;
+ struct ldb_message_element *el;
+ struct ldb_val gv, *test_gv;
+ gid_t itergid;
+
+ /* 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", data->gid);
+
+ data->attrs = sysdb_new_attrs(data);
+ if (ret != EOK) {
+ fail("Could not create the changeset");
+ return;
+ }
+
+ ghostname = talloc_asprintf(data, "testghost%d", _i);
+ fail_unless(ghostname != NULL, "Out of memory\n");
+ ret = sysdb_attrs_steal_string(data->attrs, SYSDB_GHOST, ghostname);
+ fail_unless(ret == EOK, "Cannot add attr\n");
+
+ data->attrlist = talloc_array(data, const char *, 2);
+ fail_unless(data->attrlist != NULL, "talloc_array failed.");
+ data->attrlist[0] = SYSDB_GHOST;
+ data->attrlist[1] = NULL;
+
+ /* Before the add, the groups should not contain the ghost attribute */
+ for (itergid = data->gid ; itergid < MBO_GROUP_BASE + NUM_GHOSTS; itergid++) {
+ ret = sysdb_search_group_by_gid(data, test_ctx->sysdb,
+ itergid,
+ data->attrlist, &data->msg);
+ fail_if(ret != EOK, "Cannot retrieve group %llu\n",
+ (unsigned long long) data->gid);
+
+ gv.data = (uint8_t *) ghostname;
+ gv.length = strlen(ghostname);
+
+ el = ldb_msg_find_element(data->msg, SYSDB_GHOST);
+ if (data->gid > MBO_GROUP_BASE) {
+ /* The first group would have the ghost attribute gone completely */
+ fail_if(el == NULL, "Cannot find ghost element\n");
+ test_gv = ldb_msg_find_val(el, &gv);
+ fail_unless(test_gv == NULL,
+ "Ghost user %s unexpectedly found\n", ghostname);
+ } else {
+ fail_unless(el == NULL, "Stray values in ghost element?\n");
+ }
+ }
+
+ /* Perform the add operation */
+ ret = sysdb_set_group_attr(test_ctx->sysdb, data->groupname,
+ data->attrs, SYSDB_MOD_ADD);
+ fail_unless(ret == EOK, "Cannot set group attrs\n");
+ talloc_free(test_ctx);
+
+ /* Before the delete, all groups with gid >= _i have the testuser%_i
+ * as a member
+ */
+ for (itergid = data->gid ; itergid < MBO_GROUP_BASE + NUM_GHOSTS; itergid++) {
+ ret = sysdb_search_group_by_gid(data, test_ctx->sysdb,
+ itergid,
+ data->attrlist, &data->msg);
+ fail_if(ret != EOK, "Cannot retrieve group %llu\n",
+ (unsigned long long) data->gid);
+
+ gv.data = (uint8_t *) ghostname;
+ gv.length = strlen(ghostname);
+
+ el = ldb_msg_find_element(data->msg, SYSDB_GHOST);
+ fail_if(el == NULL, "Cannot find ghost element\n");
+
+ test_gv = ldb_msg_find_val(el, &gv);
+ fail_if(test_gv == NULL, "Cannot find ghost user %s\n", ghostname);
+ }
+
+}
+END_TEST
+
+START_TEST (test_sysdb_memberof_mod_replace)
+{
+ struct sysdb_test_ctx *test_ctx;
+ struct test_data *data;
+ char *ghostname_del;
+ char *ghostname_add;
+ int ret;
+ struct ldb_message_element *el;
+ struct ldb_val gv, *test_gv;
+ gid_t itergid;
+
+ /* 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", data->gid);
+
+ data->attrs = sysdb_new_attrs(data);
+ if (ret != EOK) {
+ fail("Could not create the changeset");
+ return;
+ }
+
+ /* The test replaces the testuser%i attribute with testghost%i */
+ ghostname_del = talloc_asprintf(data, "testuser%d", _i);
+ fail_unless(ghostname_del != NULL, "Out of memory\n");
+
+ ghostname_add = talloc_asprintf(data, "testghost%d", _i);
+ fail_unless(ghostname_add != NULL, "Out of memory\n");
+ ret = sysdb_attrs_steal_string(data->attrs, SYSDB_GHOST, ghostname_add);
+ fail_unless(ret == EOK, "Cannot add attr\n");
+
+ data->attrlist = talloc_array(data, const char *, 2);
+ fail_unless(data->attrlist != NULL, "talloc_array failed.");
+ data->attrlist[0] = SYSDB_GHOST;
+ data->attrlist[1] = NULL;
+
+ /* Before the replace, all groups with gid >= _i have the testuser%_i
+ * as a member
+ */
+ for (itergid = data->gid ; itergid < MBO_GROUP_BASE + NUM_GHOSTS; itergid++) {
+ ret = sysdb_search_group_by_gid(data, test_ctx->sysdb,
+ itergid,
+ data->attrlist, &data->msg);
+ fail_if(ret != EOK, "Cannot retrieve group %llu\n",
+ (unsigned long long) data->gid);
+
+ gv.data = (uint8_t *) ghostname_del;
+ gv.length = strlen(ghostname_del);
+
+ el = ldb_msg_find_element(data->msg, SYSDB_GHOST);
+ fail_if(el == NULL, "Cannot find ghost element\n");
+
+ test_gv = ldb_msg_find_val(el, &gv);
+ fail_if(test_gv == NULL, "Cannot find ghost user %s\n", ghostname_del);
+ }
+
+ /* Perform the replace operation */
+ ret = sysdb_set_group_attr(test_ctx->sysdb, data->groupname,
+ data->attrs, SYSDB_MOD_REP);
+ fail_unless(ret == EOK, "Cannot set group attrs\n");
+
+ /* After the replace, all groups with gid >= _i have the testghost%_i
+ * as a member
+ */
+ for (itergid = data->gid ; itergid < MBO_GROUP_BASE + NUM_GHOSTS; itergid++) {
+ ret = sysdb_search_group_by_gid(data, test_ctx->sysdb,
+ itergid,
+ data->attrlist, &data->msg);
+ fail_if(ret != EOK, "Cannot retrieve group %llu\n",
+ (unsigned long long) data->gid);
+
+ gv.data = (uint8_t *) ghostname_add;
+ gv.length = strlen(ghostname_add);
+
+ el = ldb_msg_find_element(data->msg, SYSDB_GHOST);
+ fail_if(el == NULL, "Cannot find ghost element\n");
+
+ test_gv = ldb_msg_find_val(el, &gv);
+ fail_if(test_gv == NULL, "Cannot find ghost user %s\n", ghostname_add);
+ }
+
+}
+END_TEST
+
START_TEST (test_sysdb_memberof_close_loop)
{
struct sysdb_test_ctx *test_ctx;
@@ -2367,6 +2551,97 @@ START_TEST (test_sysdb_memberof_remove_child_group_and_check_ghost)
}
END_TEST
+START_TEST (test_sysdb_memberof_mod_del)
+{
+ struct sysdb_test_ctx *test_ctx;
+ struct test_data *data;
+ char *ghostname;
+ int ret;
+ struct ldb_message_element *el;
+ struct ldb_val gv, *test_gv;
+ gid_t itergid;
+
+ /* 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", data->gid);
+
+ data->attrs = sysdb_new_attrs(data);
+ if (ret != EOK) {
+ fail("Could not create the changeset");
+ return;
+ }
+
+ ghostname = talloc_asprintf(data, "testuser%d", _i);
+ fail_unless(ghostname != NULL, "Out of memory\n");
+ ret = sysdb_attrs_steal_string(data->attrs, SYSDB_GHOST, ghostname);
+ fail_unless(ret == EOK, "Cannot add attr\n");
+
+ data->attrlist = talloc_array(data, const char *, 2);
+ fail_unless(data->attrlist != NULL, "talloc_array failed.");
+ data->attrlist[0] = SYSDB_GHOST;
+ data->attrlist[1] = NULL;
+
+ /* Before the delete, all groups with gid >= _i have the testuser%_i
+ * as a member
+ */
+ for (itergid = data->gid ; itergid < MBO_GROUP_BASE + NUM_GHOSTS; itergid++) {
+ ret = sysdb_search_group_by_gid(data, test_ctx->sysdb,
+ itergid,
+ data->attrlist, &data->msg);
+ fail_if(ret != EOK, "Cannot retrieve group %llu\n",
+ (unsigned long long) data->gid);
+
+ gv.data = (uint8_t *) ghostname;
+ gv.length = strlen(ghostname);
+
+ el = ldb_msg_find_element(data->msg, SYSDB_GHOST);
+ fail_if(el == NULL, "Cannot find ghost element\n");
+
+ test_gv = ldb_msg_find_val(el, &gv);
+ fail_if(test_gv == NULL, "Cannot find ghost user %s\n", ghostname);
+ }
+
+ /* Delete the attribute */
+ ret = sysdb_set_group_attr(test_ctx->sysdb, data->groupname,
+ data->attrs, SYSDB_MOD_DEL);
+ fail_unless(ret == EOK, "Cannot set group attrs\n");
+
+ /* After the delete, we shouldn't be able to find the ghost attribute */
+ for (itergid = data->gid ; itergid < MBO_GROUP_BASE + NUM_GHOSTS; itergid++) {
+ ret = sysdb_search_group_by_gid(data, test_ctx->sysdb,
+ itergid,
+ data->attrlist, &data->msg);
+ fail_if(ret != EOK, "Cannot retrieve group %llu\n",
+ (unsigned long long) data->gid);
+
+ gv.data = (uint8_t *) ghostname;
+ gv.length = strlen(ghostname);
+
+ el = ldb_msg_find_element(data->msg, SYSDB_GHOST);
+ if (itergid > data->gid) {
+ /* The first group would have the ghost attribute gone completely */
+ fail_if(el == NULL, "Cannot find ghost element\n");
+ test_gv = ldb_msg_find_val(el, &gv);
+ fail_unless(test_gv == NULL,
+ "Ghost user %s unexpectedly found\n", ghostname);
+ } else {
+ fail_unless(el == NULL, "Stray values in ghost element?\n");
+ }
+ }
+
+ talloc_free(test_ctx);
+}
+END_TEST
+
START_TEST (test_sysdb_memberof_check_ghost)
{
struct sysdb_test_ctx *test_ctx;
@@ -2521,6 +2796,170 @@ START_TEST (test_sysdb_memberof_check_convert)
}
END_TEST
+START_TEST (test_sysdb_memberof_ghost_replace)
+{
+ struct sysdb_test_ctx *test_ctx;
+ struct test_data *data;
+ char *ghostname_del;
+ char *ghostname_add;
+ int ret;
+ struct ldb_message_element *el;
+ struct ldb_val gv, *test_gv;
+
+ /* 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", data->gid);
+
+ data->attrs = sysdb_new_attrs(data);
+ if (ret != EOK) {
+ fail("Could not create the changeset");
+ return;
+ }
+
+ /* The test replaces the testghost%i attribute with testuser%i */
+ ghostname_del = talloc_asprintf(data, "testghost%d", _i - 1);
+ fail_unless(ghostname_del != NULL, "Out of memory\n");
+
+ ghostname_add = talloc_asprintf(data, "testuser%d", _i - 1);
+ fail_unless(ghostname_add != NULL, "Out of memory\n");
+ ret = sysdb_attrs_steal_string(data->attrs, SYSDB_GHOST, ghostname_add);
+ fail_unless(ret == EOK, "Cannot add attr\n");
+
+ data->attrlist = talloc_array(data, const char *, 2);
+ fail_unless(data->attrlist != NULL, "talloc_array failed.");
+ data->attrlist[0] = SYSDB_GHOST;
+ data->attrlist[1] = NULL;
+
+ /* Before the replace, the group has the testghost%_i as a member */
+ ret = sysdb_search_group_by_gid(data, test_ctx->sysdb,
+ data->gid,
+ data->attrlist, &data->msg);
+ fail_if(ret != EOK, "Cannot retrieve group %llu\n",
+ (unsigned long long) data->gid);
+
+ gv.data = (uint8_t *) ghostname_del;
+ gv.length = strlen(ghostname_del);
+
+ el = ldb_msg_find_element(data->msg, SYSDB_GHOST);
+ fail_if(el == NULL, "Cannot find ghost element\n");
+
+ test_gv = ldb_msg_find_val(el, &gv);
+ fail_if(test_gv == NULL, "Cannot find ghost user %s\n", ghostname_del);
+
+ /* Perform the replace operation */
+ ret = sysdb_set_group_attr(test_ctx->sysdb, data->groupname,
+ data->attrs, SYSDB_MOD_REP);
+ fail_unless(ret == EOK, "Cannot set group attrs\n");
+
+ /* After the replace, the group has the testghost%_i as a member */
+ ret = sysdb_search_group_by_gid(data, test_ctx->sysdb,
+ data->gid,
+ data->attrlist, &data->msg);
+ fail_if(ret != EOK, "Cannot retrieve group %llu\n",
+ (unsigned long long) data->gid);
+
+ gv.data = (uint8_t *) ghostname_add;
+ gv.length = strlen(ghostname_add);
+
+ el = ldb_msg_find_element(data->msg, SYSDB_GHOST);
+ fail_if(el == NULL, "Cannot find ghost element\n");
+
+ test_gv = ldb_msg_find_val(el, &gv);
+ fail_if(test_gv == NULL, "Cannot find ghost user %s\n", ghostname_add);
+}
+END_TEST
+
+START_TEST (test_sysdb_memberof_ghost_replace_noop)
+{
+ struct sysdb_test_ctx *test_ctx;
+ struct test_data *data;
+ char *ghostname_del;
+ char *ghostname_add;
+ int ret;
+ struct ldb_message_element *el;
+ struct ldb_val gv, *test_gv;
+
+ /* 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", data->gid);
+
+ data->attrs = sysdb_new_attrs(data);
+ if (ret != EOK) {
+ fail("Could not create the changeset");
+ return;
+ }
+
+ /* The test replaces the testghost%i attribute with testuser%i */
+ ghostname_del = talloc_asprintf(data, "testuser%d", _i - 1);
+ fail_unless(ghostname_del != NULL, "Out of memory\n");
+
+ ghostname_add = talloc_asprintf(data, "testuser%d", _i - 1);
+ fail_unless(ghostname_add != NULL, "Out of memory\n");
+ ret = sysdb_attrs_steal_string(data->attrs, SYSDB_GHOST, ghostname_add);
+ fail_unless(ret == EOK, "Cannot add attr\n");
+
+ data->attrlist = talloc_array(data, const char *, 2);
+ fail_unless(data->attrlist != NULL, "talloc_array failed.");
+ data->attrlist[0] = SYSDB_GHOST;
+ data->attrlist[1] = NULL;
+
+ /* Before the replace, the group has the testghost%_i as a member */
+ ret = sysdb_search_group_by_gid(data, test_ctx->sysdb,
+ data->gid,
+ data->attrlist, &data->msg);
+ fail_if(ret != EOK, "Cannot retrieve group %llu\n",
+ (unsigned long long) data->gid);
+
+ gv.data = (uint8_t *) ghostname_del;
+ gv.length = strlen(ghostname_del);
+
+ el = ldb_msg_find_element(data->msg, SYSDB_GHOST);
+ fail_if(el == NULL, "Cannot find ghost element\n");
+
+ test_gv = ldb_msg_find_val(el, &gv);
+ fail_if(test_gv == NULL, "Cannot find ghost user %s\n", ghostname_del);
+
+ /* Perform the replace operation */
+ ret = sysdb_set_group_attr(test_ctx->sysdb, data->groupname,
+ data->attrs, SYSDB_MOD_REP);
+ fail_unless(ret == EOK, "Cannot set group attrs\n");
+
+ /* After the replace, the group has the testghost%_i as a member */
+ ret = sysdb_search_group_by_gid(data, test_ctx->sysdb,
+ data->gid,
+ data->attrlist, &data->msg);
+ fail_if(ret != EOK, "Cannot retrieve group %llu\n",
+ (unsigned long long) data->gid);
+
+ gv.data = (uint8_t *) ghostname_add;
+ gv.length = strlen(ghostname_add);
+
+ el = ldb_msg_find_element(data->msg, SYSDB_GHOST);
+ fail_if(el == NULL, "Cannot find ghost element\n");
+
+ test_gv = ldb_msg_find_val(el, &gv);
+ fail_if(test_gv == NULL, "Cannot find ghost user %s\n", ghostname_add);
+}
+END_TEST
+
START_TEST (test_sysdb_memberof_user_cleanup)
{
struct sysdb_test_ctx *test_ctx;
@@ -4395,7 +4834,7 @@ Suite *create_sysdb_suite(void)
tcase_add_test(tc_sysdb, test_sysdb_svc_remove_alias);
/* Add all test cases to the test suite */
- suite_add_tcase(s, tc_sysdb);
+ //suite_add_tcase(s, tc_sysdb);
TCase *tc_memberof = tcase_create("SYSDB member/memberof/memberuid Tests");
@@ -4456,12 +4895,53 @@ Suite *create_sysdb_suite(void)
/* Check the members and ghosts are there as appropriate */
tcase_add_loop_test(tc_memberof, test_sysdb_memberof_check_convert,
MBO_GROUP_BASE , MBO_GROUP_BASE + NUM_GHOSTS);
+ /* Rename the other half */
+ tcase_add_loop_test(tc_memberof, test_sysdb_memberof_ghost_replace,
+ MBO_GROUP_BASE + NUM_GHOSTS/2 + 1,
+ MBO_GROUP_BASE + NUM_GHOSTS);
+ /* Attempt to replace with the same data to check if noop works correctly */
+ tcase_add_loop_test(tc_memberof, test_sysdb_memberof_ghost_replace_noop,
+ MBO_GROUP_BASE + NUM_GHOSTS/2 + 1,
+ MBO_GROUP_BASE + NUM_GHOSTS);
/* Remove the real users */
tcase_add_loop_test(tc_memberof, test_sysdb_memberof_user_cleanup,
MBO_GROUP_BASE , MBO_GROUP_BASE + NUM_GHOSTS/2);
tcase_add_loop_test(tc_memberof, test_sysdb_remove_local_group_by_gid,
MBO_GROUP_BASE , MBO_GROUP_BASE + NUM_GHOSTS);
+ /* ghost users - memberof mod_del */
+ tcase_add_loop_test(tc_memberof, test_sysdb_memberof_store_group_with_ghosts,
+ MBO_GROUP_BASE , MBO_GROUP_BASE + 10);
+ tcase_add_loop_test(tc_memberof, test_sysdb_memberof_check_nested_ghosts,
+ MBO_GROUP_BASE , MBO_GROUP_BASE + 10);
+ tcase_add_loop_test(tc_memberof, test_sysdb_memberof_mod_del,
+ MBO_GROUP_BASE , MBO_GROUP_BASE + 10);
+ tcase_add_loop_test(tc_memberof, test_sysdb_remove_local_group_by_gid,
+ MBO_GROUP_BASE , MBO_GROUP_BASE + NUM_GHOSTS);
+
+ /* ghost users - memberof mod_add */
+ /* Add groups without ghosts first */
+ tcase_add_loop_test(tc_memberof, test_sysdb_memberof_store_group, 0, 10);
+ /* Add ghosts to groups so that they propagate */
+ tcase_add_loop_test(tc_memberof, test_sysdb_memberof_mod_add,
+ MBO_GROUP_BASE , MBO_GROUP_BASE + 10);
+ /* Check if the ghosts in fact propagated */
+ tcase_add_loop_test(tc_memberof, test_sysdb_memberof_check_nested_ghosts,
+ MBO_GROUP_BASE , MBO_GROUP_BASE + 10);
+ /* Clean up */
+ tcase_add_loop_test(tc_memberof, test_sysdb_remove_local_group_by_gid,
+ MBO_GROUP_BASE , MBO_GROUP_BASE + 10);
+
+ /* ghost users - replace */
+ tcase_add_loop_test(tc_memberof, test_sysdb_memberof_store_group_with_ghosts,
+ MBO_GROUP_BASE , MBO_GROUP_BASE + 10);
+ tcase_add_loop_test(tc_memberof, test_sysdb_memberof_check_nested_ghosts,
+ MBO_GROUP_BASE , MBO_GROUP_BASE + 10);
+ tcase_add_loop_test(tc_memberof, test_sysdb_memberof_mod_replace,
+ MBO_GROUP_BASE , MBO_GROUP_BASE + 10);
+ tcase_add_loop_test(tc_memberof, test_sysdb_remove_local_group_by_gid,
+ MBO_GROUP_BASE , MBO_GROUP_BASE + 10);
+
suite_add_tcase(s, tc_memberof);
TCase *tc_subdomain = tcase_create("SYSDB sub-domain Tests");
@@ -4471,7 +4951,7 @@ Suite *create_sysdb_suite(void)
tcase_add_test(tc_subdomain, test_sysdb_subdomain_user_ops);
tcase_add_test(tc_subdomain, test_sysdb_subdomain_group_ops);
- suite_add_tcase(s, tc_subdomain);
+ //suite_add_tcase(s, tc_subdomain);
#ifdef BUILD_AUTOFS
TCase *tc_autofs = tcase_create("SYSDB autofs Tests");
@@ -4499,7 +4979,7 @@ Suite *create_sysdb_suite(void)
tcase_add_test(tc_subdomain, test_autofs_get_duplicate_keys);
- suite_add_tcase(s, tc_autofs);
+ //suite_add_tcase(s, tc_autofs);
#endif
return s;
--
1.8.0
More information about the sssd-devel
mailing list