1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-26 10:04:02 +03:00

added support for parentGUID

This is made up of 4 parts:

  1) change our schema to include the parentGUID attribute type

  2) in the add hook in the objectclass module, get the objectGUID of
  the parent and add it to the message as parentGUID

  3) in the rename hook in the objectclass module, get the objectGUID
  of the new parent, and insert an async modify request after the
  renmam is done

  4) added a simple test suite
This commit is contained in:
Andrew Tridgell 2009-03-17 14:18:53 +11:00
parent 1a06b31b59
commit a1ebb85020
3 changed files with 129 additions and 5 deletions

View File

@ -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;

View File

@ -90,6 +90,36 @@ class BasicTests(unittest.TestCase):
except LdbError, (num, _):
self.assertEquals(num, ERR_NO_SUCH_OBJECT)
def test_parentGUID(self):
"""Test parentGUID behaviour"""
print "Testing parentGUID behaviour\n"
self.ldb.add({
"dn": "cn=parentguidtest,cn=users," + self.base_dn,
"objectclass":"user",
"samaccountname":"parentguidtest"});
res1 = ldb.search(base="cn=parentguidtest,cn=users," + self.base_dn, scope=SCOPE_BASE,
attrs=["parentGUID"]);
res2 = ldb.search(base="cn=users," + self.base_dn,scope=SCOPE_BASE,
attrs=["objectGUID"]);
self.assertEquals(res1[0]["parentGUID"], res2[0]["objectGUID"]);
"""Test parentGUID behaviour"""
print "Testing parentGUID behaviour on rename\n"
self.ldb.add({
"dn": "cn=testotherusers," + self.base_dn,
"objectclass":"container"});
res1 = ldb.search(base="cn=testotherusers," + self.base_dn,scope=SCOPE_BASE,
attrs=["objectGUID"]);
ldb.rename("cn=parentguidtest,cn=users," + self.base_dn,
"cn=parentguidtest,cn=testotherusers," + self.base_dn);
res2 = ldb.search(base="cn=parentguidtest,cn=testotherusers," + self.base_dn,
scope=SCOPE_BASE,
attrs=["parentGUID"]);
self.assertEquals(res1[0]["objectGUID"], res2[0]["parentGUID"]);
def test_all(self):
"""Basic tests"""

View File

@ -4096,6 +4096,21 @@ systemOnly: TRUE
systemFlags: 19
isMemberOfPartialAttributeSet: TRUE
dn: CN=Parent-GUID,${SCHEMADN}
objectClass: top
objectClass: attributeSchema
cn: Parent-GUID
ldapDisplayName: parentGUID
attributeId: 1.2.840.113556.1.4.1224
attributeSyntax: 2.5.5.10
omSyntax: 4
isSingleValued: TRUE
schemaIdGuid: 2df90d74-009f-11d2-aa4c-00c04fd7d83a
systemOnly: TRUE
searchFlags: 0
systemFlags: 134217748
schemaFlagsEx: 1
dn: CN=ms-DS-Tasks-For-Az-Task-BL,${SCHEMADN}
objectClass: top
objectClass: attributeSchema