summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorSimo Sorce <ssorce@redhat.com>2009-08-12 14:01:37 -0400
committerSimo Sorce <ssorce@redhat.com>2009-08-24 11:03:36 -0400
commited9879124a2b5dc0d788b7a8c5067fc0a6ef62c6 (patch)
treedcf8a30a254128598ffa70b91f9b09610bbe1570 /server
parentee51d9d5136421271b831c61f7792831264abc19 (diff)
downloadsssd-ed9879124a2b5dc0d788b7a8c5067fc0a6ef62c6.tar.gz
sssd-ed9879124a2b5dc0d788b7a8c5067fc0a6ef62c6.tar.xz
sssd-ed9879124a2b5dc0d788b7a8c5067fc0a6ef62c6.zip
Relax memberof constraints a bit
Allow to try to set members that do not actually exist. In that case simply remove them when we find out they are not real entries.
Diffstat (limited to 'server')
-rw-r--r--server/ldb_modules/memberof.c311
1 files changed, 226 insertions, 85 deletions
diff --git a/server/ldb_modules/memberof.c b/server/ldb_modules/memberof.c
index 07db63d1e..b15191603 100644
--- a/server/ldb_modules/memberof.c
+++ b/server/ldb_modules/memberof.c
@@ -20,6 +20,10 @@
#include <string.h>
#include "ldb_module.h"
+#ifndef talloc_zfree
+#define talloc_zfree(ptr) do { talloc_free(ptr); ptr = NULL; } while(0)
+#endif
+
#ifndef MAX
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#endif
@@ -57,6 +61,12 @@ struct mbof_add_ctx {
struct mbof_add_operation *add_list;
struct mbof_add_operation *current_op;
+
+ struct ldb_message *msg;
+ struct ldb_dn *msg_dn;
+ bool terminate;
+
+ struct mbof_dn *missing;
};
struct mbof_del_ancestors_ctx {
@@ -101,6 +111,9 @@ struct mbof_mod_ctx {
struct ldb_message *entry;
struct mbof_dn_array *to_add;
+
+ struct ldb_message *msg;
+ bool terminate;
};
static struct mbof_ctx *mbof_init(struct ldb_module *module,
@@ -193,6 +206,8 @@ 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_missing(struct mbof_add_ctx *add_ctx, struct ldb_dn *dn);
+static int mbof_add_cleanup(struct mbof_add_ctx *add_ctx);
static int memberof_add(struct ldb_module *module, struct ldb_request *req)
{
@@ -200,7 +215,7 @@ static int memberof_add(struct ldb_module *module, struct ldb_request *req)
struct mbof_add_ctx *add_ctx;
struct mbof_ctx *ctx;
struct ldb_request *add_req;
- const struct ldb_message_element *el;
+ struct ldb_message_element *el;
struct mbof_dn_array *parents;
struct ldb_dn *valdn;
int i, ret;
@@ -210,20 +225,6 @@ static int memberof_add(struct ldb_module *module, struct ldb_request *req)
return ldb_next_request(module, req);
}
- /* fail operation if memberof is ever specified */
- el = ldb_msg_find_element(req->op.add.message, "memberof");
- if (el) {
- /* FIXME: should we simply filter it instead ? */
- ldb_debug(ldb, LDB_DEBUG_TRACE, "the memberof attrinbute is readonly");
- return LDB_ERR_CONSTRAINT_VIOLATION;
- }
-
- /* continue with normal ops if there are no members */
- el = ldb_msg_find_element(req->op.add.message, "member");
- if (!el) {
- return ldb_next_request(module, req);
- }
-
ctx = mbof_init(module, req);
if (!ctx) {
return LDB_ERR_OPERATIONS_ERROR;
@@ -233,9 +234,29 @@ static int memberof_add(struct ldb_module *module, struct ldb_request *req)
if (!add_ctx) {
return LDB_ERR_OPERATIONS_ERROR;
}
-
add_ctx->ctx = ctx;
+ add_ctx->msg = ldb_msg_copy(add_ctx, req->op.add.message);
+ if (!add_ctx->msg) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ add_ctx->msg_dn = add_ctx->msg->dn;
+
+ /* ignore memberof if specified */
+ el = ldb_msg_find_element(add_ctx->msg, "memberof");
+ if (el) {
+ ldb_debug(ldb, LDB_DEBUG_ERROR,
+ "the memberof attribute is readonly. Ignoring.");
+ ldb_msg_remove_element(add_ctx->msg, el);
+ }
+
+ /* continue with normal ops if there are no members */
+ el = ldb_msg_find_element(add_ctx->msg, "member");
+ if (!el) {
+ add_ctx->terminate = true;
+ goto done;
+ }
+
parents = talloc_zero(add_ctx, struct mbof_dn_array);
if (!parents) {
return LDB_ERR_OPERATIONS_ERROR;
@@ -244,7 +265,7 @@ static int memberof_add(struct ldb_module *module, struct ldb_request *req)
if (!parents->dns) {
return LDB_ERR_OPERATIONS_ERROR;
}
- parents->dns[0] = req->op.add.message->dn;
+ parents->dns[0] = add_ctx->msg_dn;
parents->num = 1;
/* process new members */
@@ -252,14 +273,14 @@ static int memberof_add(struct ldb_module *module, struct ldb_request *req)
for (i = 0; i < el->num_values; i++) {
valdn = ldb_dn_from_ldb_val(add_ctx, ldb, &el->values[i]);
if (!valdn || !ldb_dn_validate(valdn)) {
- ldb_debug(ldb, LDB_DEBUG_TRACE, "Invalid dn value: [%s]",
+ ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid dn value: [%s]",
(const char *)el->values[i].data);
return LDB_ERR_INVALID_DN_SYNTAX;
}
if (ldb_dn_compare(valdn, req->op.add.message->dn) == 0) {
- ldb_debug(ldb, LDB_DEBUG_TRACE, "Adding self as member is not permitted!");
- ldb_set_errstring(ldb, "Adding self as member is not permitted!");
- return LDB_ERR_CONSTRAINT_VIOLATION;
+ ldb_debug(ldb, LDB_DEBUG_ERROR,
+ "Adding self as member is not permitted! Skipping");
+ continue;
}
ret = mbof_append_addop(add_ctx, parents, valdn);
if (ret != LDB_SUCCESS) {
@@ -267,9 +288,10 @@ static int memberof_add(struct ldb_module *module, struct ldb_request *req)
}
}
+done:
/* add original object */
ret = ldb_build_add_req(&add_req, ldb, add_ctx,
- req->op.add.message, req->controls,
+ add_ctx->msg, req->controls,
add_ctx, mbof_add_callback,
req);
if (ret != LDB_SUCCESS) {
@@ -303,7 +325,7 @@ static int mbof_add_callback(struct ldb_request *req,
switch (ares->type) {
case LDB_REPLY_ENTRY:
/* shouldn't happen */
- talloc_free(ares);
+ talloc_zfree(ares);
return ldb_module_done(ctx->req, NULL, NULL,
LDB_ERR_OPERATIONS_ERROR);
case LDB_REPLY_REFERRAL:
@@ -311,6 +333,13 @@ static int mbof_add_callback(struct ldb_request *req,
break;
case LDB_REPLY_DONE:
+ if (add_ctx->terminate) {
+ return ldb_module_done(ctx->req,
+ ctx->ret_ctrls,
+ ctx->ret_resp,
+ LDB_SUCCESS);
+ }
+
if (add_ctx->current_op == NULL) {
/* first operation */
ctx->ret_ctrls = talloc_steal(ctx, ares->controls);
@@ -323,20 +352,24 @@ static int mbof_add_callback(struct ldb_request *req,
}
else {
/* no more operations */
- talloc_free(ares);
- return ldb_module_done(ctx->req,
- ctx->ret_ctrls,
- ctx->ret_resp,
- LDB_SUCCESS);
+ if (add_ctx->missing) {
+ ret = mbof_add_cleanup(add_ctx);
+ }
+ else {
+ return ldb_module_done(ctx->req,
+ ctx->ret_ctrls,
+ ctx->ret_resp,
+ LDB_SUCCESS);
+ }
}
if (ret != LDB_SUCCESS) {
- talloc_free(ares);
+ talloc_zfree(ares);
return ldb_module_done(ctx->req, NULL, NULL, ret);
}
}
- talloc_free(ares);
+ talloc_zfree(ares);
return LDB_SUCCESS;
}
@@ -415,22 +448,46 @@ static int mbof_next_add_callback(struct ldb_request *req,
break;
case LDB_REPLY_DONE:
+ talloc_zfree(ares);
if (addop->entry == NULL) {
ldb_debug(ldb, LDB_DEBUG_TRACE, "Entry not found (%s)",
ldb_dn_get_linearized(addop->entry_dn));
- /* this target does not exists, too bad! */
- return ldb_module_done(ctx->req, NULL, NULL,
- LDB_ERR_CONSTRAINT_VIOLATION);
- }
- ret = mbof_add_operation(addop);
- if (ret != LDB_SUCCESS) {
- talloc_free(ares);
- return ldb_module_done(ctx->req, NULL, NULL, ret);
+ /* this target does not exists, save as missing */
+ ret = mbof_add_missing(add_ctx, addop->entry_dn);
+ if (ret != LDB_SUCCESS) {
+ return ldb_module_done(ctx->req, NULL, NULL, ret);
+ }
+ /* now try the next operation */
+ if (add_ctx->current_op->next) {
+ ret = mbof_next_add(add_ctx->current_op->next);
+ }
+ else {
+ /* no more operations */
+ if (add_ctx->missing) {
+ ret = mbof_add_cleanup(add_ctx);
+ }
+ else {
+ return ldb_module_done(ctx->req,
+ ctx->ret_ctrls,
+ ctx->ret_resp,
+ LDB_SUCCESS);
+ }
+ }
+ if (ret != LDB_SUCCESS) {
+ return ldb_module_done(ctx->req, NULL, NULL, ret);
+ }
+ }
+ else {
+ ret = mbof_add_operation(addop);
+ if (ret != LDB_SUCCESS) {
+ return ldb_module_done(ctx->req, NULL, NULL, ret);
+ }
}
+ return LDB_SUCCESS;
}
- talloc_free(ares);
+ talloc_zfree(ares);
return LDB_SUCCESS;
}
@@ -592,6 +649,80 @@ static int mbof_add_operation(struct mbof_add_operation *addop)
return ldb_next_request(ctx->module, mod_req);
}
+static int mbof_add_missing(struct mbof_add_ctx *add_ctx, struct ldb_dn *dn)
+{
+ struct mbof_dn *mdn;
+
+ mdn = talloc(add_ctx, struct mbof_dn);
+ if (!mdn) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ mdn->dn = talloc_steal(mdn, dn);
+
+ /* add to the list */
+ mdn->next = add_ctx->missing;
+ add_ctx->missing = mdn;
+
+ return LDB_SUCCESS;
+}
+
+/* remove unexisting members */
+static int mbof_add_cleanup(struct mbof_add_ctx *add_ctx)
+{
+ struct ldb_context *ldb;
+ struct ldb_message *msg;
+ struct ldb_request *mod_req;
+ struct ldb_message_element *el;
+ struct mbof_ctx *ctx;
+ struct mbof_dn *iter;
+ const char *val;
+ int ret, i, num;
+
+ ctx = add_ctx->ctx;
+ ldb = ldb_module_get_ctx(ctx->module);
+
+ num = 0;
+ for (iter = add_ctx->missing; iter; iter = iter->next) {
+ num++;
+ }
+ if (num == 0) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ msg = ldb_msg_new(add_ctx);
+ if (!msg) return LDB_ERR_OPERATIONS_ERROR;
+
+ msg->dn = add_ctx->msg_dn;
+
+ ret = ldb_msg_add_empty(msg, "member", LDB_FLAG_MOD_DELETE, &el);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ el->values = talloc_array(msg, struct ldb_val, num);
+ if (!el->values) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ el->num_values = num;
+ for (i = 0, iter = add_ctx->missing; iter; iter = iter->next, i++) {
+ val = ldb_dn_get_linearized(iter->dn);
+ el->values[i].length = strlen(val);
+ el->values[i].data = (uint8_t *)talloc_strdup(el->values, val);
+ if (!el->values[i].data) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ }
+
+ add_ctx->terminate = true;
+ ret = ldb_build_mod_req(&mod_req, ldb, add_ctx,
+ msg, NULL,
+ add_ctx, mbof_add_callback,
+ ctx->req);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ return ldb_next_request(ctx->module, mod_req);
+}
@@ -833,12 +964,12 @@ static int mbof_del_search_callback(struct ldb_request *req,
/* now perform the requested delete, before proceeding further */
ret = mbof_orig_del(del_ctx);
if (ret != LDB_SUCCESS) {
- talloc_free(ares);
+ talloc_zfree(ares);
return ldb_module_done(ctx->req, NULL, NULL, ret);
}
}
- talloc_free(ares);
+ talloc_zfree(ares);
return LDB_SUCCESS;
}
@@ -885,7 +1016,7 @@ static int mbof_orig_del_callback(struct ldb_request *req,
}
if (ares->type != LDB_REPLY_DONE) {
- talloc_free(ares);
+ talloc_zfree(ares);
ldb_set_errstring(ldb, "Invalid reply type!");
return ldb_module_done(ctx->req, NULL, NULL,
LDB_ERR_OPERATIONS_ERROR);
@@ -912,11 +1043,11 @@ static int mbof_orig_del_callback(struct ldb_request *req,
LDB_SUCCESS);
}
if (ret != LDB_SUCCESS) {
- talloc_free(ares);
+ talloc_zfree(ares);
return ldb_module_done(ctx->req, NULL, NULL, ret);
}
- talloc_free(ares);
+ talloc_zfree(ares);
return LDB_SUCCESS;
}
@@ -995,7 +1126,7 @@ static int mbof_del_clean_par_callback(struct ldb_request *req,
}
if (ares->type != LDB_REPLY_DONE) {
- talloc_free(ares);
+ talloc_zfree(ares);
ldb_set_errstring(ldb, "Invalid reply type!");
return ldb_module_done(ctx->req, NULL, NULL,
LDB_ERR_OPERATIONS_ERROR);
@@ -1021,11 +1152,11 @@ static int mbof_del_clean_par_callback(struct ldb_request *req,
}
if (ret != LDB_SUCCESS) {
- talloc_free(ares);
+ talloc_zfree(ares);
return ldb_module_done(ctx->req, NULL, NULL, ret);
}
- talloc_free(ares);
+ talloc_zfree(ares);
return LDB_SUCCESS;
}
@@ -1214,7 +1345,7 @@ static int mbof_del_exop_search_callback(struct ldb_request *req,
}
}
- talloc_free(ares);
+ talloc_zfree(ares);
return LDB_SUCCESS;
}
@@ -1421,7 +1552,7 @@ static int mbof_del_anc_callback(struct ldb_request *req,
}
}
- talloc_free(ares);
+ talloc_zfree(ares);
return LDB_SUCCESS;
}
@@ -1522,12 +1653,12 @@ static int mbof_del_mod_callback(struct ldb_request *req,
case LDB_REPLY_ENTRY:
ldb_debug(ldb, LDB_DEBUG_TRACE, "Got an entry on a non search op ?!");
/* shouldn't happen */
- talloc_free(ares);
+ talloc_zfree(ares);
return ldb_module_done(ctx->req, NULL, NULL,
LDB_ERR_OPERATIONS_ERROR);
case LDB_REPLY_REFERRAL:
/* ignore */
- talloc_free(ares);
+ talloc_zfree(ares);
break;
case LDB_REPLY_DONE:
@@ -1535,7 +1666,7 @@ static int mbof_del_mod_callback(struct ldb_request *req,
ret = mbof_del_progeny(delop);
if (ret != LDB_SUCCESS) {
- talloc_free(ares);
+ talloc_zfree(ares);
return ldb_module_done(ctx->req, NULL, NULL, ret);
}
}
@@ -1686,7 +1817,7 @@ static int mbof_fill_dn_array(TALLOC_CTX *memctx,
static int memberof_mod(struct ldb_module *module, struct ldb_request *req)
{
- const struct ldb_message_element *el;
+ struct ldb_message_element *el;
struct mbof_mod_ctx *mod_ctx;
struct mbof_ctx *ctx;
static const char *attrs[] = {"member", "memberof", NULL};
@@ -1699,20 +1830,6 @@ static int memberof_mod(struct ldb_module *module, struct ldb_request *req)
return ldb_next_request(module, req);
}
- /* fail operation if memberof is ever specified */
- el = ldb_msg_find_element(req->op.mod.message, "memberof");
- if (el) {
- ldb_debug(ldb, LDB_DEBUG_TRACE, "the memberof attrinbute is readonly");
- /* FIXME: should we simply filter it instead ? */
- return LDB_ERR_CONSTRAINT_VIOLATION;
- }
-
- /* continue with normal ops if there are no members */
- el = ldb_msg_find_element(req->op.mod.message, "member");
- if (!el) {
- return ldb_next_request(module, req);
- }
-
/* TODO: fail if this is not a group ? */
ctx = mbof_init(module, req);
@@ -1720,18 +1837,39 @@ static int memberof_mod(struct ldb_module *module, struct ldb_request *req)
return LDB_ERR_OPERATIONS_ERROR;
}
- /* can't do anything,
- * must check first what's on the entry */
mod_ctx = talloc_zero(ctx, struct mbof_mod_ctx);
if (!mod_ctx) {
talloc_free(ctx);
return LDB_ERR_OPERATIONS_ERROR;
}
mod_ctx->ctx = ctx;
+
+ mod_ctx->msg = ldb_msg_copy(mod_ctx, req->op.mod.message);
+ if (!mod_ctx->msg) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ /* fail operation if memberof is ever specified */
+ el = ldb_msg_find_element(mod_ctx->msg, "memberof");
+ if (el) {
+ ldb_debug(ldb, LDB_DEBUG_ERROR,
+ "the memberof attribute is readonly. Ignoring.");
+ ldb_msg_remove_element(mod_ctx->msg, el);
+ }
+
+ /* continue with normal ops if there are no members */
+ el = ldb_msg_find_element(mod_ctx->msg, "member");
+ if (!el) {
+ 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,
- req->op.mod.message->dn, LDB_SCOPE_BASE,
+ mod_ctx->msg->dn, LDB_SCOPE_BASE,
NULL, attrs, NULL,
mod_ctx, mbof_mod_callback,
req);
@@ -1772,7 +1910,7 @@ static int mbof_mod_callback(struct ldb_request *req,
if (mod_ctx->entry != NULL) {
ldb_debug(ldb, LDB_DEBUG_TRACE,
"Found multiple entries for (%s)",
- ldb_dn_get_linearized(mod_ctx->entry->dn));
+ ldb_dn_get_linearized(mod_ctx->msg->dn));
/* more than one entry per dn ?? db corrupted ? */
return ldb_module_done(ctx->req, NULL, NULL,
LDB_ERR_OPERATIONS_ERROR);
@@ -1791,7 +1929,7 @@ static int mbof_mod_callback(struct ldb_request *req,
case LDB_REPLY_DONE:
if (mod_ctx->entry == NULL) {
ldb_debug(ldb, LDB_DEBUG_TRACE, "Entry not found (%s)",
- ldb_dn_get_linearized(req->op.mod.message->dn));
+ ldb_dn_get_linearized(mod_ctx->msg->dn));
/* this target does not exists, too bad! */
return ldb_module_done(ctx->req, NULL, NULL,
LDB_ERR_NO_SUCH_OBJECT);
@@ -1799,12 +1937,12 @@ static int mbof_mod_callback(struct ldb_request *req,
ret = mbof_orig_mod(mod_ctx);
if (ret != LDB_SUCCESS) {
- talloc_free(ares);
+ talloc_zfree(ares);
return ldb_module_done(ctx->req, NULL, NULL, ret);
}
}
- talloc_free(ares);
+ talloc_zfree(ares);
return LDB_SUCCESS;
}
@@ -1819,7 +1957,7 @@ static int mbof_orig_mod(struct mbof_mod_ctx *mod_ctx)
ldb = ldb_module_get_ctx(ctx->module);
ret = ldb_build_mod_req(&mod_req, ldb, ctx->req,
- ctx->req->op.mod.message, ctx->req->controls,
+ mod_ctx->msg, ctx->req->controls,
mod_ctx, mbof_orig_mod_callback,
ctx->req);
if (ret != LDB_SUCCESS) {
@@ -1835,7 +1973,6 @@ static int mbof_orig_mod_callback(struct ldb_request *req,
struct ldb_context *ldb;
struct mbof_mod_ctx *mod_ctx;
struct mbof_ctx *ctx;
- bool done = false;
int ret;
mod_ctx = talloc_get_type(req->context, struct mbof_mod_ctx);
@@ -1854,7 +1991,7 @@ static int mbof_orig_mod_callback(struct ldb_request *req,
}
if (ares->type != LDB_REPLY_DONE) {
- talloc_free(ares);
+ talloc_zfree(ares);
ldb_debug(ldb, LDB_DEBUG_TRACE, "Invalid reply type!");
ldb_set_errstring(ldb, "Invalid reply type!");
return ldb_module_done(ctx->req, NULL, NULL,
@@ -1865,21 +2002,24 @@ static int mbof_orig_mod_callback(struct ldb_request *req,
ctx->ret_ctrls = talloc_steal(ctx, ares->controls);
ctx->ret_resp = talloc_steal(ctx, ares->response);
- /* next step */
- ret = mbof_mod_process(mod_ctx, &done);
- if (ret != LDB_SUCCESS) {
- talloc_free(ares);
- return ldb_module_done(ctx->req, NULL, NULL, ret);
+ if (!mod_ctx->terminate) {
+ /* next step */
+ ret = mbof_mod_process(mod_ctx, &mod_ctx->terminate);
+ if (ret != LDB_SUCCESS) {
+ talloc_zfree(ares);
+ return ldb_module_done(ctx->req, NULL, NULL, ret);
+ }
}
- if (done) {
- talloc_free(ares);
+
+ if (mod_ctx->terminate) {
+ talloc_zfree(ares);
return ldb_module_done(ctx->req,
ctx->ret_ctrls,
ctx->ret_resp,
LDB_SUCCESS);
}
- talloc_free(ares);
+ talloc_zfree(ares);
return LDB_SUCCESS;
}
@@ -2037,6 +2177,7 @@ static int mbof_mod_add(struct mbof_mod_ctx *mod_ctx,
return LDB_ERR_OPERATIONS_ERROR;
}
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]);