diff options
Diffstat (limited to 'source4/dsdb/samdb/ldb_modules/objectclass.c')
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/objectclass.c | 89 |
1 files changed, 84 insertions, 5 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/objectclass.c b/source4/dsdb/samdb/ldb_modules/objectclass.c index 898d913965..7883bccfe7 100644 --- a/source4/dsdb/samdb/ldb_modules/objectclass.c +++ b/source4/dsdb/samdb/ldb_modules/objectclass.c @@ -414,6 +414,7 @@ static int objectclass_add(struct ldb_module *module, struct ldb_request *req) struct oc_context *ac; struct ldb_dn *parent_dn; int ret; + static const char * const parent_attrs[] = { "objectGUID", NULL }; ldb = ldb_module_get_ctx(module); @@ -449,7 +450,7 @@ static int objectclass_add(struct ldb_module *module, struct ldb_request *req) ret = ldb_build_search_req(&search_req, ldb, ac, parent_dn, LDB_SCOPE_BASE, - "(objectClass=*)", NULL, + "(objectClass=*)", parent_attrs, NULL, ac, get_search_callback, req); @@ -500,7 +501,8 @@ static int objectclass_do_add(struct oc_context *ac) return LDB_ERR_UNWILLING_TO_PERFORM; } } else { - + const struct ldb_val *parent_guid; + /* Fix up the DN to be in the standard form, taking particular care to match the parent DN */ ret = fix_dn(msg, ac->req->op.add.message->dn, @@ -514,10 +516,24 @@ static int objectclass_do_add(struct oc_context *ac) return ret; } + parent_guid = ldb_msg_find_ldb_val(ac->search_res->message, "objectGUID"); + if (parent_guid == NULL) { + ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, parent does not have an objectGUID!", + ldb_dn_get_linearized(msg->dn)); + talloc_free(mem_ctx); + return LDB_ERR_UNWILLING_TO_PERFORM; + } + /* TODO: Check this is a valid child to this parent, * by reading the allowedChildClasses and * allowedChildClasssesEffective attributes */ - + ret = ldb_msg_add_steal_value(msg, "parentGUID", discard_const(parent_guid)); + if (ret != LDB_SUCCESS) { + ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, failed to add parentGUID", + ldb_dn_get_linearized(msg->dn)); + talloc_free(mem_ctx); + return LDB_ERR_UNWILLING_TO_PERFORM; + } } if (schema) { @@ -974,7 +990,7 @@ static int objectclass_do_rename(struct oc_context *ac); static int objectclass_rename(struct ldb_module *module, struct ldb_request *req) { - static const char * const attrs[] = { NULL }; + static const char * const attrs[] = { "objectGUID", NULL }; struct ldb_context *ldb; struct ldb_request *search_req; struct oc_context *ac; @@ -1007,6 +1023,9 @@ static int objectclass_rename(struct ldb_module *module, struct ldb_request *req ldb_oom(ldb); return LDB_ERR_OPERATIONS_ERROR; } + + /* note that the results of this search are kept and used to + update the parentGUID in objectclass_rename_callback() */ ret = ldb_build_search_req(&search_req, ldb, ac, parent_dn, LDB_SCOPE_BASE, "(objectClass=*)", @@ -1022,6 +1041,66 @@ static int objectclass_rename(struct ldb_module *module, struct ldb_request *req return ldb_next_request(ac->module, search_req); } +/* + called after the rename happens. + We now need to fix the parentGUID of the object to be the objectGUID of + the new parent +*/ +static int objectclass_rename_callback(struct ldb_request *req, struct ldb_reply *ares) +{ + struct ldb_context *ldb; + struct oc_context *ac; + const struct ldb_val *parent_guid; + struct ldb_request *mod_req = NULL; + int ret; + struct ldb_message *msg; + struct ldb_message_element *el = NULL; + + ac = talloc_get_type(req->context, struct oc_context); + ldb = ldb_module_get_ctx(ac->module); + + /* make sure the rename succeeded */ + if (!ares) { + return ldb_module_done(ac->req, NULL, NULL, + LDB_ERR_OPERATIONS_ERROR); + } + if (ares->error != LDB_SUCCESS) { + return ldb_module_done(ac->req, ares->controls, + ares->response, ares->error); + } + + + /* the ac->search_res should contain the new parents objectGUID */ + parent_guid = ldb_msg_find_ldb_val(ac->search_res->message, "objectGUID"); + if (parent_guid == NULL) { + ldb_asprintf_errstring(ldb, "objectclass: Cannot rename %s, new parent does not have an objectGUID!", + ldb_dn_get_linearized(ac->req->op.rename.newdn)); + return LDB_ERR_UNWILLING_TO_PERFORM; + + } + + /* construct the modify message */ + msg = ldb_msg_new(ac); + if (msg == NULL) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + msg->dn = ac->req->op.rename.newdn; + + ret = ldb_msg_add_value(msg, "parentGUID", parent_guid, &el); + if (ret != LDB_SUCCESS) { + return ret; + } + + el->flags = LDB_FLAG_MOD_REPLACE; + + ret = ldb_build_mod_req(&mod_req, ldb, ac, msg, + NULL, ac, oc_op_callback, req); + + return ldb_next_request(ac->module, mod_req); +} + static int objectclass_do_rename(struct oc_context *ac) { struct ldb_context *ldb; @@ -1055,7 +1134,7 @@ static int objectclass_do_rename(struct oc_context *ac) ret = ldb_build_rename_req(&rename_req, ldb, ac, ac->req->op.rename.olddn, fixed_dn, ac->req->controls, - ac, oc_op_callback, + ac, objectclass_rename_callback, ac->req); if (ret != LDB_SUCCESS) { return ret; |