summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2009-03-17 14:18:53 +1100
committerAndrew Tridgell <tridge@samba.org>2009-03-17 14:18:53 +1100
commita1ebb850209289734b12ea966b01d295d8fc436d (patch)
tree3e37143eeaaad05f9c70f301cee5cf825c624988
parent1a06b31b592a9c1d0188f4470b38e881b0bf3633 (diff)
downloadsamba-a1ebb850209289734b12ea966b01d295d8fc436d.tar.gz
samba-a1ebb850209289734b12ea966b01d295d8fc436d.tar.bz2
samba-a1ebb850209289734b12ea966b01d295d8fc436d.zip
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
-rw-r--r--source4/dsdb/samdb/ldb_modules/objectclass.c89
-rwxr-xr-xsource4/lib/ldb/tests/python/ldap.py30
-rw-r--r--source4/setup/schema.ldif15
3 files changed, 129 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;
diff --git a/source4/lib/ldb/tests/python/ldap.py b/source4/lib/ldb/tests/python/ldap.py
index a30273fc66..7d2c7d0547 100755
--- a/source4/lib/ldb/tests/python/ldap.py
+++ b/source4/lib/ldb/tests/python/ldap.py
@@ -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"""
diff --git a/source4/setup/schema.ldif b/source4/setup/schema.ldif
index 56eb7ce0c0..a4dfaea7eb 100644
--- a/source4/setup/schema.ldif
+++ b/source4/setup/schema.ldif
@@ -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