diff options
author | Andrew Tridgell <tridge@samba.org> | 2009-03-17 14:18:53 +1100 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2009-03-17 14:18:53 +1100 |
commit | a1ebb850209289734b12ea966b01d295d8fc436d (patch) | |
tree | 3e37143eeaaad05f9c70f301cee5cf825c624988 | |
parent | 1a06b31b592a9c1d0188f4470b38e881b0bf3633 (diff) | |
download | samba-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.c | 89 | ||||
-rwxr-xr-x | source4/lib/ldb/tests/python/ldap.py | 30 | ||||
-rw-r--r-- | source4/setup/schema.ldif | 15 |
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 |