[SCM] Samba Shared Repository - branch master updated - tevent-0-9-8-953-gbe938ab

Matthias Dieter Wallnöfer mdw at samba.org
Sat Oct 3 04:49:48 MDT 2009


The branch, master has been updated
       via  be938ab44b6095818501b23ca8422c731e14015a (commit)
       via  4bc9a39eed3e47cd87ea8cd24f9ac4f9e2712f43 (commit)
       via  0e028fcb7d141d68de2baadeb2c0fae262f2bedc (commit)
       via  f86beaaad96ac2dd7cf6a3a9d57f42c57c2440c2 (commit)
      from  dac0346906b7494f203e1e56b8f2e18c93fc2912 (commit)

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


- Log -----------------------------------------------------------------
commit be938ab44b6095818501b23ca8422c731e14015a
Author: Matthias Dieter Wallnöfer <mwallnoefer at yahoo.de>
Date:   Sat Oct 3 11:37:30 2009 +0200

    s4:ldap.py - add tests for valid parent and RDN

commit 4bc9a39eed3e47cd87ea8cd24f9ac4f9e2712f43
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Thu Sep 24 15:14:49 2009 -0700

    s4:dsdb Use possibleInferiors to restrict creation of child objects
    
    This also uses systemPossibleInferiors when the 'relax' control is
    specified, which is done by the provision.
    
    Andrew Bartlett

commit 0e028fcb7d141d68de2baadeb2c0fae262f2bedc
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Thu Sep 24 15:12:49 2009 -0700

    s4:dsdb add systemPossibleInferiors to schema code
    
    This allows us to figure out what the system can add, which will not
    be in possibleInferiors due to the systemOnly flag.
    
    Andrew Bartlett

commit f86beaaad96ac2dd7cf6a3a9d57f42c57c2440c2
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Wed Sep 23 21:16:42 2009 -0700

    s4:dsdb Add objectClass and RDN constraints to objectClass module
    
    These additional constraints are applied, found by the Microsoft testsuite.
    
     - When the parent is not present, we now return 'NO_SUCH_OBJECT'.
     - Restrict the choice of RDN to the correct one per the schema
     - Honour the allowedChildClasses attribute from the parent's objectClass.
    
    Andrew Bartlett

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

Summary of changes:
 source4/dsdb/samdb/ldb_modules/objectclass.c |   54 ++++++++++++++++++++++----
 source4/dsdb/schema/schema.h                 |    1 +
 source4/dsdb/schema/schema_inferiors.c       |   20 +++++++++
 source4/lib/ldb/tests/python/ldap.py         |   39 ++++++++++++++++++
 4 files changed, 106 insertions(+), 8 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source4/dsdb/samdb/ldb_modules/objectclass.c b/source4/dsdb/samdb/ldb_modules/objectclass.c
index b3d5461..51a1ac8 100644
--- a/source4/dsdb/samdb/ldb_modules/objectclass.c
+++ b/source4/dsdb/samdb/ldb_modules/objectclass.c
@@ -2,7 +2,7 @@
    ldb database library
 
    Copyright (C) Simo Sorce  2006-2008
-   Copyright (C) Andrew Bartlett <abartlet at samba.org> 2005-2007
+   Copyright (C) Andrew Bartlett <abartlet at samba.org> 2005-2009
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -42,6 +42,7 @@
 #include "libcli/security/security.h"
 #include "auth/auth.h"
 #include "param/param.h"
+#include "../libds/common/flags.h"
 
 struct oc_context {
 
@@ -381,7 +382,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 };
+	static const char * const parent_attrs[] = { "objectGUID", "objectClass", NULL };
 
 	ldb = ldb_module_get_ctx(module);
 
@@ -465,7 +466,7 @@ static int objectclass_do_add(struct oc_context *ac)
 			ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, parent does not exist!", 
 					       ldb_dn_get_linearized(msg->dn));
 			talloc_free(mem_ctx);
-			return LDB_ERR_UNWILLING_TO_PERFORM;
+			return LDB_ERR_NO_SUCH_OBJECT;
 		}
 	} else {
 		const struct ldb_val *parent_guid;
@@ -491,9 +492,6 @@ static int objectclass_do_add(struct oc_context *ac)
 			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", 
@@ -555,12 +553,52 @@ static int objectclass_do_add(struct oc_context *ac)
 				struct ldb_message_element *el;
 				int32_t systemFlags = 0;
 				const char *rdn_name = ldb_dn_get_rdn_name(msg->dn);
-				if (ldb_attr_cmp(rdn_name, current->objectclass->rDNAttID) != 0) {
-					ldb_asprintf_errstring(ldb, "RDN %s is not correct for most specific structural objectclass %s, should be %s", 
+				if (current->objectclass->rDNAttID
+				    && ldb_attr_cmp(rdn_name, current->objectclass->rDNAttID) != 0) {
+					ldb_asprintf_errstring(ldb,
+							       "RDN %s is not correct for most specific structural objectclass %s, should be %s",
 							       rdn_name, current->objectclass->lDAPDisplayName, current->objectclass->rDNAttID);
 					return LDB_ERR_NAMING_VIOLATION;
 				}
 
+				if (ac->search_res && ac->search_res->message) {
+					struct ldb_message_element *oc_el
+						= ldb_msg_find_element(ac->search_res->message, "objectClass");
+
+					bool allowed_class = false;
+					int i, j;
+					for (i=0; allowed_class == false && oc_el && i < oc_el->num_values; i++) {
+						const struct dsdb_class *sclass;
+
+						sclass = dsdb_class_by_lDAPDisplayName_ldb_val(schema, &oc_el->values[i]);
+						if (!sclass) {
+							/* We don't know this class?  what is going on? */
+							continue;
+						}
+						if (ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
+							for (j=0; sclass->systemPossibleInferiors && sclass->systemPossibleInferiors[j]; j++) {
+								if (ldb_attr_cmp(current->objectclass->lDAPDisplayName, sclass->systemPossibleInferiors[j]) == 0) {
+									allowed_class = true;
+									break;
+								}
+							}
+						} else {
+							for (j=0; sclass->systemPossibleInferiors && sclass->systemPossibleInferiors[j]; j++) {
+								if (ldb_attr_cmp(current->objectclass->lDAPDisplayName, sclass->systemPossibleInferiors[j]) == 0) {
+									allowed_class = true;
+									break;
+								}
+							}
+						}
+					}
+
+					if (!allowed_class) {
+						ldb_asprintf_errstring(ldb, "structural objectClass %s is not a valid child class for %s",
+							       current->objectclass->lDAPDisplayName, ldb_dn_get_linearized(ac->search_res->message->dn));
+						return LDB_ERR_NAMING_VIOLATION;
+					}
+				}
+
 				if (current->objectclass->systemOnly && !ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
 					ldb_asprintf_errstring(ldb, "objectClass %s is systemOnly, rejecting creation of %s",
 							       current->objectclass->lDAPDisplayName, ldb_dn_get_linearized(msg->dn));
diff --git a/source4/dsdb/schema/schema.h b/source4/dsdb/schema/schema.h
index 4e7e503..ddd9b37 100644
--- a/source4/dsdb/schema/schema.h
+++ b/source4/dsdb/schema/schema.h
@@ -119,6 +119,7 @@ struct dsdb_class {
 	const char **mustContain;
 	const char **mayContain;
 	const char **possibleInferiors;
+	const char **systemPossibleInferiors;
 
 	const char *defaultSecurityDescriptor;
 
diff --git a/source4/dsdb/schema/schema_inferiors.c b/source4/dsdb/schema/schema_inferiors.c
index b02d557..264e471 100644
--- a/source4/dsdb/schema/schema_inferiors.c
+++ b/source4/dsdb/schema/schema_inferiors.c
@@ -198,6 +198,25 @@ static void schema_fill_possible_inferiors(struct dsdb_schema *schema, struct ds
 	schema_class->possibleInferiors = str_list_unique(schema_class->possibleInferiors);
 }
 
+static void schema_fill_system_possible_inferiors(struct dsdb_schema *schema, struct dsdb_class *schema_class)
+{
+	struct dsdb_class *c2;
+
+	for (c2=schema->classes; c2; c2=c2->next) {
+		char **superiors = schema_posssuperiors(schema, c2);
+		if (c2->objectClassCategory != 2
+		    && c2->objectClassCategory != 3
+		    && str_list_check(superiors, schema_class->lDAPDisplayName)) {
+			if (schema_class->possibleInferiors == NULL) {
+				schema_class->systemPossibleInferiors = str_list_make_empty(schema_class);
+			}
+			schema_class->systemPossibleInferiors = str_list_add_const(schema_class->systemPossibleInferiors,
+										   c2->lDAPDisplayName);
+		}
+	}
+	schema_class->systemPossibleInferiors = str_list_unique(schema_class->systemPossibleInferiors);
+}
+
 /*
   fill in a string class name from a governs_ID
  */
@@ -285,6 +304,7 @@ void schema_fill_constructed(struct dsdb_schema *schema)
 
 	for (schema_class=schema->classes; schema_class; schema_class=schema_class->next) {
 		schema_fill_possible_inferiors(schema, schema_class);
+		schema_fill_system_possible_inferiors(schema, schema_class);
 	}
 
 	/* free up our internal cache elements */
diff --git a/source4/lib/ldb/tests/python/ldap.py b/source4/lib/ldb/tests/python/ldap.py
index 7fa25fb..59bb5d2 100755
--- a/source4/lib/ldb/tests/python/ldap.py
+++ b/source4/lib/ldb/tests/python/ldap.py
@@ -21,6 +21,7 @@ from ldb import ERR_ENTRY_ALREADY_EXISTS, ERR_UNWILLING_TO_PERFORM
 from ldb import ERR_NOT_ALLOWED_ON_NON_LEAF, ERR_OTHER, ERR_INVALID_DN_SYNTAX
 from ldb import ERR_NO_SUCH_ATTRIBUTE, ERR_INSUFFICIENT_ACCESS_RIGHTS
 from ldb import ERR_OBJECT_CLASS_VIOLATION, ERR_NOT_ALLOWED_ON_RDN
+from ldb import ERR_NAMING_VIOLATION
 from ldb import Message, MessageElement, Dn, FLAG_MOD_ADD, FLAG_MOD_REPLACE
 from samba import Ldb, param, dom_sid_to_rid
 from samba import UF_NORMAL_ACCOUNT, UF_TEMP_DUPLICATE_ACCOUNT
@@ -118,6 +119,8 @@ class BasicTests(unittest.TestCase):
         self.delete_force(self.ldb, "cn=parentguidtest,cn=testotherusers," + self.base_dn)
         self.delete_force(self.ldb, "cn=testotherusers," + self.base_dn)
         self.delete_force(self.ldb, "cn=ldaptestobject," + self.base_dn)
+        self.delete_force(self.ldb, "description=xyz,cn=users," + self.base_dn)
+        self.delete_force(self.ldb, "ou=testou,cn=users," + self.base_dn)
 
     def test_system_only(self):
         """Test systemOnly objects"""
@@ -133,6 +136,32 @@ class BasicTests(unittest.TestCase):
 
         self.delete_force(self.ldb, "cn=ldaptestobject," + self.base_dn)
 
+    def test_invalid_parent(self):
+        """Test adding an object with invalid parent"""
+        print "Test adding an object with invalid parent"""
+
+        try:
+            self.ldb.add({
+                "dn": "cn=ldaptestgroup,cn=thisdoesnotexist123,"
+                   + self.base_dn,
+                "objectclass": "group"})
+            self.fail()
+        except LdbError, (num, _):
+            self.assertEquals(num, ERR_NO_SUCH_OBJECT)
+
+        self.delete_force(self.ldb, "cn=ldaptestgroup,cn=thisdoesnotexist123,"
+          + self.base_dn)
+
+        try:
+            self.ldb.add({
+                "dn": "ou=testou,cn=users," + self.base_dn,
+                "objectclass": "organizationalUnit"})
+            self.fail()
+        except LdbError, (num, _):
+            self.assertEquals(num, ERR_NAMING_VIOLATION)
+
+        self.delete_force(self.ldb, "ou=testou,cn=users," + self.base_dn)
+
     def test_invalid_attribute(self):
         """Test adding invalid attributes (not in schema)"""
         print "Test adding invalid attributes (not in schema)"""
@@ -188,6 +217,16 @@ class BasicTests(unittest.TestCase):
         """Tests the RDN"""
         print "Tests the RDN"""
 
+        try:
+            self.ldb.add({
+                 "dn": "description=xyz,cn=users," + self.base_dn,
+                 "objectclass": "group"})
+            self.fail()
+        except LdbError, (num, _):
+            self.assertEquals(num, ERR_NAMING_VIOLATION)
+ 
+        self.delete_force(self.ldb, "description=xyz,cn=users," + self.base_dn)
+
         self.ldb.add({
              "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
              "objectclass": "group"})


-- 
Samba Shared Repository


More information about the samba-cvs mailing list