summaryrefslogtreecommitdiff
path: root/src/ldb_modules
diff options
context:
space:
mode:
authorJakub Hrozek <jhrozek@redhat.com>2012-11-27 16:09:23 +0100
committerJakub Hrozek <jhrozek@redhat.com>2012-12-05 23:32:18 +0100
commit521bc8907ac558320042f229691274d5aa7e55f0 (patch)
tree50cbc21bd3b6a0b7958dfcd0155c8147f569c99f /src/ldb_modules
parent562021e560a3be3f996551b297cada3cf8ce6cab (diff)
downloadsssd-521bc8907ac558320042f229691274d5aa7e55f0.tar.gz
sssd-521bc8907ac558320042f229691274d5aa7e55f0.tar.bz2
sssd-521bc8907ac558320042f229691274d5aa7e55f0.zip
MEMBEROF: Implement the modify operation for ghost users
Similar to the add and delete operation, we also need to propagate the changes of the ghost user attribute to the parent groups so that if a nested group updates memberships, its parents also get the membership updated.
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 *