summaryrefslogtreecommitdiff
path: root/src/ldb_modules
diff options
context:
space:
mode:
Diffstat (limited to 'src/ldb_modules')
-rw-r--r--src/ldb_modules/memberof.c271
1 files changed, 235 insertions, 36 deletions
diff --git a/src/ldb_modules/memberof.c b/src/ldb_modules/memberof.c
index 4899b03c..cb6f8113 100644
--- a/src/ldb_modules/memberof.c
+++ b/src/ldb_modules/memberof.c
@@ -41,6 +41,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;
@@ -143,11 +148,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;
};
@@ -2275,7 +2284,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)
{
@@ -2334,7 +2344,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 */
@@ -2615,7 +2626,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,
@@ -2727,7 +2739,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,
@@ -2780,19 +2793,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;
@@ -2835,15 +2859,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,
@@ -3016,16 +3040,24 @@ 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 we have something to remove do it first */
- 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 there is nothing to remove and we have stuff to add
* do it right away */
- 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,
@@ -3133,8 +3165,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;
@@ -3154,14 +3287,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;
@@ -3169,18 +3294,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;
@@ -3205,25 +3354,39 @@ static int mbof_mod_delete(struct mbof_mod_ctx *mod_ctx,
}
del_ctx->first = first;
+ /* add followup function if we also have stuff to add */
+ if ((mod_ctx->mb_add && mod_ctx->mb_add->num > 0) ||
+ (mod_ctx->gh_add && mod_ctx->gh_add->num > 0)) {
+ del_ctx->follow_mod = mod_ctx;
+ }
+
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 (delgh != NULL) {
+ ret = mbof_del_fill_ghop_ex(del_ctx, del_ctx->first->entry,
+ delgh->vals, delgh->num);
if (ret != LDB_SUCCESS) {
return ret;
}
}
- /* add followup function if we also have stuff to add */
- if (mod_ctx->mb_add) {
- del_ctx->follow_mod = mod_ctx;
+ /* 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]);
}
- /* 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,
@@ -3264,6 +3427,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 *