[SCM] Samba Shared Repository - branch master updated

Matthias Dieter Wallnöfer mdw at samba.org
Sun Nov 15 06:27:00 MST 2009


The branch, master has been updated
       via  cc08074... ldb:python bindings - add a context on "py_ldb_delete"
       via  6cf43db... s4:ldap.py - enhance schema addition test
       via  df95d5c... s4:dsdb/repl/replicated_objects - Applicate also here the new "lDAPDisplayName" generator
       via  2c7294b... s4:SAMLDB module - Add support for required and generated schema attributes
       via  da3d471... s4:samdb util - add a call for generating a correct "lDAPDisplayName"
      from  bf4e8ba... s3: Fix a memleak in sys_popen

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit cc080742bd29d56f863abcb33f26d1719dacaaf7
Author: Matthias Dieter Wallnöfer <mwallnoefer at yahoo.de>
Date:   Sun Nov 15 14:23:32 2009 +0100

    ldb:python bindings - add a context on "py_ldb_delete"
    
    So the converted DN will be freed after usage.

commit 6cf43db7fc3e2eea2cd72a026b8cd20012387e12
Author: Matthias Dieter Wallnöfer <mwallnoefer at yahoo.de>
Date:   Fri Nov 13 22:31:53 2009 +0100

    s4:ldap.py - enhance schema addition test
    
    Don't add only a new objectclass but also a new attribute. Plus let now the
    server itself calculate the "lDAPDisplayName" attribute and compare the result.

commit df95d5c29292968b465bff24c3cf78800677a4d4
Author: Matthias Dieter Wallnöfer <mwallnoefer at yahoo.de>
Date:   Sat Nov 14 20:14:45 2009 +0100

    s4:dsdb/repl/replicated_objects - Applicate also here the new "lDAPDisplayName" generator
    
    Also here we've to be sure to generate the attribute correctly if it doesn't
    exist yet.

commit 2c7294bd8faad339d090ee7a7d8d1bb44c9837fc
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Wed Sep 23 21:14:37 2009 -0700

    s4:SAMLDB module - Add support for required and generated schema attributes
    
    This missing support found by Microsoft test suite at AD interop event.
    
    Patch by Andrew Bartlett
    Enhancements by Matthias Dieter Wallnöfer

commit da3d471d10a822713fea937b3e1951bdbdc7dc83
Author: Matthias Dieter Wallnöfer <mwallnoefer at yahoo.de>
Date:   Sat Nov 14 20:12:42 2009 +0100

    s4:samdb util - add a call for generating a correct "lDAPDisplayName"
    
    This is needed for the SAMLDB module enhancement regarding schema objects.
    The algorithm in pseudo code is located in MS-ADTS 3.1.1.2.3.4.

-----------------------------------------------------------------------

Summary of changes:
 source4/dsdb/common/util.c              |   28 +++
 source4/dsdb/repl/replicated_objects.c  |    5 +-
 source4/dsdb/samdb/ldb_modules/samldb.c |  292 ++++++++++++++++++++++++++++++-
 source4/lib/ldb/pyldb.c                 |   12 +-
 source4/lib/ldb/tests/python/ldap.py    |   52 +++++--
 5 files changed, 367 insertions(+), 22 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c
index dcbb462..4175928 100644
--- a/source4/dsdb/common/util.c
+++ b/source4/dsdb/common/util.c
@@ -37,6 +37,7 @@
 #include "param/param.h"
 #include "libcli/auth/libcli_auth.h"
 #include "librpc/gen_ndr/ndr_drsblobs.h"
+#include "system/locale.h"
 
 /*
   search the sam for the specified attributes in a specific domain, filter on
@@ -2617,3 +2618,30 @@ failed:
 	talloc_free(tmp_ctx);
 	return LDB_ERR_NO_SUCH_OBJECT;
 }
+
+/*
+ * Function which generates a "lDAPDisplayName" attribute from a "CN" one.
+ * Algorithm implemented according to MS-ADTS 3.1.1.2.3.4
+ */
+const char *samdb_cn_to_lDAPDisplayName(TALLOC_CTX *mem_ctx, const char *cn)
+{
+	char **tokens, *ret;
+	size_t i;
+
+	tokens = str_list_make(mem_ctx, cn, " -_");
+	if (tokens == NULL)
+		return NULL;
+
+	/* "tolower()" and "toupper()" should also work properly on 0x00 */
+	tokens[0][0] = tolower(tokens[0][0]);
+	for (i = 1; i < str_list_length((const char **)tokens); i++)
+		tokens[i][0] = toupper(tokens[i][0]);
+
+	ret = talloc_strdup(mem_ctx, tokens[0]);
+	for (i = 1; i < str_list_length((const char **)tokens); i++)
+		ret = talloc_asprintf_append_buffer(ret, "%s", tokens[i]);
+
+	talloc_free(tokens);
+
+	return ret;
+}
diff --git a/source4/dsdb/repl/replicated_objects.c b/source4/dsdb/repl/replicated_objects.c
index 020d5f1..043c620 100644
--- a/source4/dsdb/repl/replicated_objects.c
+++ b/source4/dsdb/repl/replicated_objects.c
@@ -153,7 +153,10 @@ static WERROR dsdb_convert_object_ex(struct ldb_context *ldb,
 		struct ldb_message_element *el;
 		el = ldb_msg_find_element(msg, rdn_attr->lDAPDisplayName);
 		if (!el) {
-			ret = ldb_msg_add_value(msg, rdn_attr->lDAPDisplayName, rdn_value, NULL);
+			/* we assume that the RDN has prefix "CN" */
+			ret = ldb_msg_add_string(msg, rdn_attr->lDAPDisplayName,
+				samdb_cn_to_lDAPDisplayName(mem_ctx,
+					(const char *) rdn_value->data));
 			if (ret != LDB_SUCCESS) {
 				return WERR_FOOBAR;
 			}
diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c
index 0f314b2..390950b 100644
--- a/source4/dsdb/samdb/ldb_modules/samldb.c
+++ b/source4/dsdb/samdb/ldb_modules/samldb.c
@@ -97,6 +97,9 @@ struct samldb_ctx {
 	/* all the async steps necessary to complete the operation */
 	struct samldb_step *steps;
 	struct samldb_step *curstep;
+
+	/* If someone set an ares to forward controls and response back to the caller */
+	struct ldb_reply *ares;
 };
 
 static struct samldb_ctx *samldb_ctx_init(struct ldb_module *module,
@@ -161,9 +164,14 @@ static int samldb_next_step(struct samldb_ctx *ac)
 		return ac->curstep->fn(ac);
 	}
 
-	/* it is an error if the last step does not properly
-	 * return to the upper module by itself */
-	return LDB_ERR_OPERATIONS_ERROR;
+	/* we exit the samldb module here */
+	/* If someone set an ares to forward controls and response back to the caller, use them */
+	if (ac->ares) {
+		return ldb_module_done(ac->req, ac->ares->controls,
+				       ac->ares->response, LDB_SUCCESS);
+	} else {
+		return ldb_module_done(ac->req, NULL, NULL, LDB_SUCCESS);
+	}
 }
 
 /*
@@ -868,6 +876,152 @@ static int samldb_notice_sid(struct samldb_ctx *ac)
 }
 
 /*
+ * samldb_set_defaultObjectCategory_callback (async)
+ */
+
+static int samldb_set_defaultObjectCategory_callback(struct ldb_request *req,
+						     struct ldb_reply *ares)
+{
+	struct ldb_context *ldb;
+	struct samldb_ctx *ac;
+	int ret;
+
+	ac = talloc_get_type(req->context, struct samldb_ctx);
+	ldb = ldb_module_get_ctx(ac->module);
+
+	if (!ares) {
+		ret = LDB_ERR_OPERATIONS_ERROR;
+		goto done;
+	}
+	if (ares->error != LDB_SUCCESS) {
+		return ldb_module_done(ac->req, ares->controls,
+					ares->response, ares->error);
+	}
+	if (ares->type != LDB_REPLY_DONE) {
+		ldb_set_errstring(ldb,
+			"Invalid reply type!\n");
+		ret = LDB_ERR_OPERATIONS_ERROR;
+		goto done;
+	}
+
+	ret = samldb_next_step(ac);
+
+done:
+	if (ret != LDB_SUCCESS) {
+		return ldb_module_done(ac->req, NULL, NULL, ret);
+	}
+
+	return LDB_SUCCESS;
+}
+
+static int samldb_set_defaultObjectCategory(struct samldb_ctx *ac)
+{
+	int ret;
+	if (ac->dn) {
+		struct ldb_request *req;
+		struct ldb_context *ldb;
+		struct ldb_message *msg = ldb_msg_new(ac);
+
+		msg->dn = ac->dn;
+
+		ldb_msg_add_empty(msg, "defaultObjectCategory", LDB_FLAG_MOD_REPLACE, NULL);
+
+		ldb_msg_add_steal_string(msg, "defaultObjectCategory", ldb_dn_alloc_linearized(msg, ac->dn));
+
+		ldb = ldb_module_get_ctx(ac->module);
+
+		ret = ldb_build_mod_req(&req, ldb, ac,
+					msg, NULL,
+					ac, samldb_set_defaultObjectCategory_callback,
+					ac->req);
+		if (ret != LDB_SUCCESS) {
+			return ret;
+		}
+
+		return ldb_next_request(ac->module, req);
+	}
+
+	ret = samldb_next_step(ac);
+	if (ret != LDB_SUCCESS) {
+		return ldb_module_done(ac->req, NULL, NULL, ret);
+	}
+	return ret;
+}
+
+/*
+ * samldb_find_for_defaultObjectCategory (async)
+ */
+
+static int samldb_find_for_defaultObjectCategory_callback(struct ldb_request *req,
+						struct ldb_reply *ares)
+{
+	struct samldb_ctx *ac;
+	int ret;
+
+	ac = talloc_get_type(req->context, struct samldb_ctx);
+
+	if (ares->error != LDB_SUCCESS) {
+		return ldb_module_done(ac->req, ares->controls,
+                                       ares->response, ares->error);
+	}
+
+	switch (ares->type) {
+	case LDB_REPLY_ENTRY:
+		ac->dn = talloc_steal(ac, ares->message->dn);
+		break;
+	case LDB_REPLY_REFERRAL:
+		/* this should not happen */
+		return ldb_module_done(ac->req, NULL, NULL,
+                                       LDB_ERR_OPERATIONS_ERROR);
+
+	case LDB_REPLY_DONE:
+		/* found or not found, go on */
+		talloc_free(ares);
+		ret = samldb_next_step(ac);
+		if (ret != LDB_SUCCESS) {
+			return ldb_module_done(ac->req, NULL, NULL, ret);
+		}
+		break;
+	}
+
+	return LDB_SUCCESS;
+}
+
+static int samldb_find_for_defaultObjectCategory(struct samldb_ctx *ac)
+{
+	struct ldb_context *ldb;
+	struct ldb_request *req;
+        int ret;
+	const char *no_attrs[] = { NULL };
+
+	ldb = ldb_module_get_ctx(ac->module);
+
+	ac->dn = NULL;
+
+        if (ldb_msg_find_element(ac->msg, "defaultObjectCategory") == NULL) {
+		ret = ldb_build_search_req(&req, ldb, ac,
+					   ac->msg->dn, LDB_SCOPE_BASE,
+					   "objectClass=classSchema", no_attrs,
+					   NULL,
+					   ac, samldb_find_for_defaultObjectCategory_callback,
+					   ac->req);
+		if (ret != LDB_SUCCESS) {
+			return ret;
+		}
+		return ldb_next_request(ac->module, req);
+	}
+
+	ret = samldb_next_step(ac);
+	if (ret != LDB_SUCCESS) {
+		return ldb_module_done(ac->req, NULL, NULL, ret);
+	}
+	return ret;
+
+}
+
+
+
+/*
  * samldb_add_entry (async)
  */
 
@@ -876,6 +1030,7 @@ static int samldb_add_entry_callback(struct ldb_request *req,
 {
 	struct ldb_context *ldb;
 	struct samldb_ctx *ac;
+	int ret;
 
 	ac = talloc_get_type(req->context, struct samldb_ctx);
 	ldb = ldb_module_get_ctx(ac->module);
@@ -895,9 +1050,14 @@ static int samldb_add_entry_callback(struct ldb_request *req,
 					LDB_ERR_OPERATIONS_ERROR);
 	}
 
-	/* we exit the samldb module here */
-	return ldb_module_done(ac->req, ares->controls,
-				ares->response, LDB_SUCCESS);
+	/* The caller may wish to get controls back from the add */
+	ac->ares = talloc_steal(ac, ares);
+
+	ret = samldb_next_step(ac);
+	if (ret != LDB_SUCCESS) {
+		return ldb_module_done(ac->req, NULL, NULL, ret);
+	}
+	return ret;
 }
 
 static int samldb_add_entry(struct samldb_ctx *ac)
@@ -975,8 +1135,102 @@ static int samldb_fill_object(struct samldb_ctx *ac, const char *type)
 		ret = samdb_find_or_add_attribute(ldb, ac->msg,
 			"groupType", "-2147483646");
 		if (ret != LDB_SUCCESS) return ret;
+	} else if (strcmp(ac->type, "classSchema") == 0) {
+		const struct ldb_val *rdn_value;
+
+		ret = samdb_find_or_add_attribute(ldb, ac->msg,
+						  "rdnAttId", "cn");
+		if (ret != LDB_SUCCESS) return ret;
+
+		rdn_value = ldb_dn_get_rdn_val(ac->msg->dn);
+		if (!ldb_msg_find_element(ac->msg, "lDAPDisplayName")) {
+			/* the RDN has prefix "CN" */
+			ret = ldb_msg_add_string(ac->msg, "lDAPDisplayName",
+				samdb_cn_to_lDAPDisplayName(ac,
+					(const char *) rdn_value->data));
+			if (ret != LDB_SUCCESS) {
+				ldb_oom(ldb);
+				return ret;
+			}
+		}
+
+		if (!ldb_msg_find_element(ac->msg, "schemaIDGUID")) {
+			enum ndr_err_code ndr_err;
+			struct ldb_val guid_value;
+			struct GUID guid;
+			/* a new GUID */
+			guid = GUID_random();
+			/* generated NDR encoded values */
+			ndr_err = ndr_push_struct_blob(&guid_value, ac->msg,
+						       NULL,
+						       &guid,
+						       (ndr_push_flags_fn_t)ndr_push_GUID);
+			if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+				ldb_oom(ldb);
+				return LDB_ERR_OPERATIONS_ERROR;
+			}
+			ret = ldb_msg_add_value(ac->msg, "schemaIDGUID", &guid_value, NULL);
+			if (ret != LDB_SUCCESS) {
+				ldb_oom(ldb);
+				return ret;
+			}
+		}
+
+		ret = samldb_add_step(ac, samldb_add_entry);
+		if (ret != LDB_SUCCESS) return ret;
+
+		ret = samldb_add_step(ac, samldb_find_for_defaultObjectCategory);
+		if (ret != LDB_SUCCESS) return ret;
+
+		ret = samldb_add_step(ac, samldb_set_defaultObjectCategory);
+		if (ret != LDB_SUCCESS) return ret;
+
+		return samldb_first_step(ac);
+	} else if (strcmp(ac->type, "attributeSchema") == 0) {
+		const struct ldb_val *rdn_value;
+		rdn_value = ldb_dn_get_rdn_val(ac->msg->dn);
+		if (!ldb_msg_find_element(ac->msg, "lDAPDisplayName")) {
+			/* the RDN has prefix "CN" */
+			ret = ldb_msg_add_string(ac->msg, "lDAPDisplayName",
+				samdb_cn_to_lDAPDisplayName(ac,
+					(const char *) rdn_value->data));
+			if (ret != LDB_SUCCESS) {
+				ldb_oom(ldb);
+				return ret;
+			}
+		}
+
+		ret = samdb_find_or_add_attribute(ldb, ac->msg,
+						  "isSingleValued", "FALSE");
+		if (ret != LDB_SUCCESS) return ret;
+
+		if (!ldb_msg_find_element(ac->msg, "schemaIDGUID")) {
+			enum ndr_err_code ndr_err;
+			struct ldb_val guid_value;
+			struct GUID guid;
+			/* a new GUID */
+			guid = GUID_random();
+			/* generated NDR encoded values */
+			ndr_err = ndr_push_struct_blob(&guid_value, ac->msg,
+						       NULL,
+						       &guid,
+						       (ndr_push_flags_fn_t)ndr_push_GUID);
+			if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+				ldb_oom(ldb);
+				return LDB_ERR_OPERATIONS_ERROR;
+			}
+			ret = ldb_msg_add_value(ac->msg, "schemaIDGUID", &guid_value, NULL);
+			if (ret != LDB_SUCCESS) {
+				ldb_oom(ldb);
+				return ret;
+			}
+		}
+
+		ret = samldb_add_step(ac, samldb_add_entry);
+		if (ret != LDB_SUCCESS) return ret;
+
+		return samldb_first_step(ac);
 	} else {
-		/* we should only have "user" and "group" */
 		ldb_asprintf_errstring(ldb,
 			"Invalid entry type!\n");
 		return LDB_ERR_OPERATIONS_ERROR;
@@ -1952,6 +2206,30 @@ static int samldb_add(struct ldb_module *module, struct ldb_request *req)
 		return samldb_fill_foreignSecurityPrincipal_object(ac);
 	}
 
+	if (samdb_find_attribute(ldb, ac->msg,
+				 "objectclass", "classSchema") != NULL) {
+
+		ret = samldb_check_rdn(module, ac->req->op.add.message->dn);
+		if (ret != LDB_SUCCESS) {
+			talloc_free(ac);
+			return ret;
+		}
+
+		return samldb_fill_object(ac, "classSchema");
+	}
+
+	if (samdb_find_attribute(ldb, ac->msg,
+				 "objectclass", "attributeSchema") != NULL) {
+
+		ret = samldb_check_rdn(module, ac->req->op.add.message->dn);
+		if (ret != LDB_SUCCESS) {
+			talloc_free(ac);
+			return ret;
+		}
+
+		return samldb_fill_object(ac, "attributeSchema");
+	}
+
 	talloc_free(ac);
 
 	/* nothing matched, go on */
diff --git a/source4/lib/ldb/pyldb.c b/source4/lib/ldb/pyldb.c
index 901d121..1f1dcf8 100644
--- a/source4/lib/ldb/pyldb.c
+++ b/source4/lib/ldb/pyldb.c
@@ -783,15 +783,23 @@ static PyObject *py_ldb_delete(PyLdbObject *self, PyObject *args)
 	struct ldb_dn *dn;
 	int ret;
 	struct ldb_context *ldb;
+	TALLOC_CTX *mem_ctx;
 	if (!PyArg_ParseTuple(args, "O", &py_dn))
 		return NULL;
 
+	mem_ctx = talloc_new(NULL);
+	if (mem_ctx == NULL) {
+		PyErr_NoMemory();
+		return NULL;
+	}
 	ldb = PyLdb_AsLdbContext(self);
-
-	if (!PyObject_AsDn(NULL, py_dn, ldb, &dn))
+	if (!PyObject_AsDn(mem_ctx, py_dn, ldb, &dn)) {
+		talloc_free(mem_ctx);
 		return NULL;
+	}
 
 	ret = ldb_delete(ldb, dn);
+	talloc_free(mem_ctx);
 	PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
 
 	Py_RETURN_NONE;
diff --git a/source4/lib/ldb/tests/python/ldap.py b/source4/lib/ldb/tests/python/ldap.py
index eb686df..a77a777 100755
--- a/source4/lib/ldb/tests/python/ldap.py
+++ b/source4/lib/ldb/tests/python/ldap.py
@@ -1895,32 +1895,46 @@ class SchemaTests(unittest.TestCase):
 
     def test_schemaUpdateNow(self):
         """Testing schemaUpdateNow"""
-        class_name = "test-class" + time.strftime("%s", time.gmtime())
+        attr_name = "test-Attr" + time.strftime("%s", time.gmtime())
+        attr_ldap_display_name = attr_name.replace("-", "")
+
+        ldif = """
+dn: CN=%s,%s""" % (attr_name, self.schema_dn) + """
+objectClass: top
+objectClass: attributeSchema
+adminDescription: """ + attr_name + """
+adminDisplayName: """ + attr_name + """
+cn: """ + attr_name + """
+attributeId: 1.2.840.""" + str(random.randint(1,100000)) + """.1.5.9940
+attributeSyntax: 2.5.5.12
+omSyntax: 64
+instanceType: 4
+isSingleValued: TRUE
+systemOnly: FALSE
+"""
+        self.ldb.add_ldif(ldif)
+
+        class_name = "test-Class" + time.strftime("%s", time.gmtime())
         class_ldap_display_name = class_name.replace("-", "")
-        object_name = "obj" + time.strftime("%s", time.gmtime())
 
         ldif = """
 dn: CN=%s,%s""" % (class_name, self.schema_dn) + """
-lDAPDisplayName: """ + class_ldap_display_name + """
 objectClass: top
 objectClass: classSchema
 adminDescription: """ + class_name + """
 adminDisplayName: """ + class_name + """
 cn: """ + class_name + """
-objectCategory: CN=Class-Schema,""" + self.schema_dn + """
-defaultObjectCategory: CN=%s,%s""" % (class_name, self.schema_dn) + """
-distinguishedName: CN=%s,%s""" % (class_name, self.schema_dn) + """
-governsID: 1.2.840.""" + str(random.randint(1,100000)) + """.1.5.9939
+governsId: 1.2.840.""" + str(random.randint(1,100000)) + """.1.5.9939
 instanceType: 4
-name: """ + class_name + """
 objectClassCategory: 1
 subClassOf: organizationalPerson
 systemFlags: 16
 rDNAttID: cn
-systemMustContain: cn
+systemMustContain: cn, """ + attr_ldap_display_name + """
 systemOnly: FALSE
 """
         self.ldb.add_ldif(ldif)
+
         ldif = """
 dn:
 changetype: modify
@@ -1928,6 +1942,9 @@ add: schemaUpdateNow
 schemaUpdateNow: 1
 """
         self.ldb.modify_ldif(ldif)
+


-- 
Samba Shared Repository


More information about the samba-cvs mailing list