[SCM] Samba Shared Repository - branch master updated

Matthias Dieter Wallnöfer mdw at samba.org
Wed Nov 3 12:31:01 MDT 2010


The branch, master has been updated
       via  4b79a74 s4:descriptor LDB module - a bit cleanup
       via  53d9d4e s4:sam.py - assign valid values when performing the special-attributes constraint checks
       via  b78bf4d s4:samldb LDB module - improve the "get_single_valued_attr" call and move it into "ldb_modules/util.c"
       via  4311438 s4:objectclass_attrs LDB module - introduce the hardcoded delete-protected attributes list
      from  0baa1fb pydsdb: Import testtools before subunit for those that don't have testtools installed.

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


- Log -----------------------------------------------------------------
commit 4b79a74c1bcb74198a911693e8027797081727cc
Author: Matthias Dieter Wallnöfer <mdw at samba.org>
Date:   Mon Nov 1 17:50:23 2010 +0100

    s4:descriptor LDB module - a bit cleanup
    
    - add more OOM checks where needed
    - remove message of an error which cannot happen anymore (since now the
      structural objectclass is always checked by the objectclass LDB module)
    
    Autobuild-User: Matthias Dieter Wallnöfer <mdw at samba.org>
    Autobuild-Date: Wed Nov  3 18:30:52 UTC 2010 on sn-devel-104

commit 53d9d4ee0e6ee889a06c2d1134ddb083be45f91a
Author: Matthias Dieter Wallnöfer <mdw at samba.org>
Date:   Wed Nov 3 18:02:28 2010 +0100

    s4:sam.py - assign valid values when performing the special-attributes constraint checks
    
    The problem is that s4 per construction does the checks in a different order. It
    first checks for validity (pre-operation trigger in samldb LDB module) and then
    for the schema (post-operation trigger in objectclass_attrs LDB module).
    constraints (post-operation trigger

commit b78bf4d72100f9aa8c50ee36b30ba353e2b72eae
Author: Matthias Dieter Wallnöfer <mdw at samba.org>
Date:   Wed Nov 3 17:50:30 2010 +0100

    s4:samldb LDB module - improve the "get_single_valued_attr" call and move it into "ldb_modules/util.c"
    
    It will be used by other LDB modules as well.

commit 4311438528aaf30fff878c3862fd1d76f6059f56
Author: Matthias Dieter Wallnöfer <mdw at samba.org>
Date:   Wed Nov 3 17:29:58 2010 +0100

    s4:objectclass_attrs LDB module - introduce the hardcoded delete-protected attributes list
    
    This is a hardcoded list in AD of attributes, which can never be deleted.

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

Summary of changes:
 source4/dsdb/samdb/ldb_modules/descriptor.c        |   47 ++++++++---
 source4/dsdb/samdb/ldb_modules/objectclass_attrs.c |   20 ++++-
 source4/dsdb/samdb/ldb_modules/samldb.c            |   90 ++------------------
 source4/dsdb/samdb/ldb_modules/util.c              |   30 +++++++
 source4/dsdb/tests/python/sam.py                   |    6 +-
 5 files changed, 92 insertions(+), 101 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source4/dsdb/samdb/ldb_modules/descriptor.c b/source4/dsdb/samdb/ldb_modules/descriptor.c
index c0b79f6..9b950af 100644
--- a/source4/dsdb/samdb/ldb_modules/descriptor.c
+++ b/source4/dsdb/samdb/ldb_modules/descriptor.c
@@ -598,15 +598,23 @@ static int descriptor_do_mod(struct descriptor_context *ac)
 
 	ldb = ldb_module_get_ctx(ac->module);
 	schema = dsdb_get_schema(ldb, ac);
+
 	msg = ldb_msg_copy_shallow(ac, ac->req->op.mod.message);
-	objectclass_element = ldb_msg_find_element(ac->search_oc_res->message, "objectClass");
-	objectclass = get_last_structural_class(schema, objectclass_element);
+	if (msg == NULL) {
+		return ldb_module_oom(ac->module);
+	}
+
+	objectclass_element = ldb_msg_find_element(ac->search_oc_res->message,
+						   "objectClass");
+	if (objectclass_element == NULL) {
+		return ldb_operr(ldb);
+	}
 
-	if (!objectclass) {
-		ldb_asprintf_errstring(ldb, "No last structural objectclass found on %s",
-				       ldb_dn_get_linearized(ac->search_oc_res->message->dn));
-		return LDB_ERR_OPERATIONS_ERROR;
+	objectclass = get_last_structural_class(schema, objectclass_element);
+	if (objectclass == NULL) {
+		return ldb_operr(ldb);
 	}
+
 	sd_control = ldb_request_get_control(ac->req, LDB_CONTROL_SD_FLAGS_OID);
 	sd_control2 = ldb_request_get_control(ac->req, LDB_CONTROL_RECALCULATE_SD_OID);
 	if (sd_control) {
@@ -675,23 +683,35 @@ static int descriptor_do_add(struct descriptor_context *ac)
 
 	ldb = ldb_module_get_ctx(ac->module);
 	schema = dsdb_get_schema(ldb, ac);
+
 	mem_ctx = talloc_new(ac);
 	if (mem_ctx == NULL) {
-		return ldb_oom(ldb);
+		return ldb_module_oom(ac->module);
 	}
+
 	switch (ac->req->operation) {
 	case LDB_ADD:
 		msg = ldb_msg_copy_shallow(ac, ac->req->op.add.message);
+		if (msg == NULL) {
+			return ldb_module_oom(ac->module);
+		}
+
 		objectclass_element = ldb_msg_find_element(msg, "objectClass");
-		objectclass = get_last_structural_class(schema, objectclass_element);
+		if (objectclass_element == NULL) {
+			return ldb_operr(ldb);
+		}
 
-		if (!objectclass) {
-			ldb_asprintf_errstring(ldb, "No last structural objectclass found on %s", ldb_dn_get_linearized(msg->dn));
-			return LDB_ERR_OPERATIONS_ERROR;
+		objectclass = get_last_structural_class(schema,
+							objectclass_element);
+		if (objectclass == NULL) {
+			return ldb_operr(ldb);
 		}
 		break;
 	case LDB_MODIFY:
 		msg = ldb_msg_copy_shallow(ac, ac->req->op.mod.message);
+		if (msg == NULL) {
+			return ldb_module_oom(ac->module);
+		}
 		break;
 	default:
 		return ldb_operr(ldb);
@@ -717,8 +737,9 @@ static int descriptor_do_add(struct descriptor_context *ac)
 	}
 
 	if (ac->req->operation == LDB_ADD) {
-	/* get the parent descriptor and the one provided. If not provided, get the default.*/
-	/* convert to security descriptor and calculate */
+		/* Get the parent descriptor and the one provided. If not
+		 * provided, get the default. Convert it to a security
+		 * descriptor and calculate the permissions. */
 		sd = get_new_descriptor(ac->module, msg->dn, mem_ctx, objectclass,
 					ac->parentsd_val, ac->sd_val, NULL, 0);
 		if (ac->sd_val) {
diff --git a/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c b/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c
index bd4e0be..62bc9ae 100644
--- a/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c
+++ b/source4/dsdb/samdb/ldb_modules/objectclass_attrs.c
@@ -240,6 +240,10 @@ static int attr_handler2(struct oc_context *ac)
 	struct ldb_message_element *oc_element;
 	struct ldb_message *msg;
 	const char **must_contain, **may_contain, **found_must_contain;
+	/* There exists a hardcoded delete-protected attributes list in AD */
+	const char *del_prot_attributes[] = { "nTSecurityDescriptor",
+		"objectSid", "sAMAccountType", "sAMAccountName", "groupType",
+		"primaryGroupID", "userAccountControl", NULL }, **l;
 	const struct dsdb_attribute *attr;
 	unsigned int i;
 	bool found;
@@ -268,9 +272,23 @@ static int attr_handler2(struct oc_context *ac)
 		return ldb_operr(ldb);
 	}
 
+	/* Check the delete-protected attributes list */
+	msg = ac->search_res->message;
+	for (l = del_prot_attributes; *l != NULL; l++) {
+		found = str_list_check_ci(must_contain, *l);
+		if (!found) {
+			found = str_list_check_ci(may_contain, *l);
+		}
+		if (found && (ldb_msg_find_element(msg, *l) == NULL)) {
+			ldb_asprintf_errstring(ldb, "objectclass_attrs: delete protected attribute '%s' on entry '%s' missing!",
+					       *l,
+					       ldb_dn_get_linearized(msg->dn));
+			return LDB_ERR_UNWILLING_TO_PERFORM;
+		}
+	}
+
 	/* Check if all specified attributes are valid in the given
 	 * objectclasses and if they meet additional schema restrictions. */
-	msg = ac->search_res->message;
 	for (i = 0; i < msg->num_elements; i++) {
 		attr = dsdb_attribute_by_lDAPDisplayName(ac->schema,
 							 msg->elements[i].name);
diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c
index 13b173a..73776ab 100644
--- a/source4/dsdb/samdb/ldb_modules/samldb.c
+++ b/source4/dsdb/samdb/ldb_modules/samldb.c
@@ -757,53 +757,6 @@ static int samldb_schema_info_update(struct samldb_ctx *ac)
 }
 
 /*
- * Gets back a single-valued attribute by the rules of the SAM triggers when
- * performing a modify operation
- */
-static int samldb_get_single_valued_attr(struct samldb_ctx *ac,
-					 const char *attr_name,
-					 struct ldb_message_element **attr)
-{
-	struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
-	struct ldb_message_element *el = NULL;
-	unsigned int i;
-
-	/* We've to walk over all modification entries and consider the
-	 * "attr_name" ones.
-	 *
-	 * 1.) Add operations aren't allowed and there is returned
-	 *     "ATTRIBUTE_OR_VALUE_EXISTS".
-	 * 2.) Replace operations are allowed but the last one is taken
-	 * 3.) Delete operations are also not allowed and there is returned
-	 *     "UNWILLING_TO_PERFORM".
-	 *
-	 * If "el" is afterwards NULL then that means we've nothing to do here.
-	 */
-	for (i = 0; i < ac->msg->num_elements; i++) {
-		if (ldb_attr_cmp(ac->msg->elements[i].name, attr_name) != 0) {
-			continue;
-		}
-
-		el = &ac->msg->elements[i];
-		if (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_ADD) {
-			ldb_asprintf_errstring(ldb,
-					       "samldb: attribute '%s' already exists!",
-					       attr_name);
-			return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
-		}
-		if (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE) {
-			ldb_asprintf_errstring(ldb,
-					       "samldb: attribute '%s' cannot be deleted!",
-					       attr_name);
-			return LDB_ERR_UNWILLING_TO_PERFORM;
-		}
-	}
-
-	*attr = el;
-	return LDB_SUCCESS;
-}
-
-/*
  * "Objectclass" trigger (MS-SAMR 3.1.1.8.1)
  *
  * Has to be invoked on "add" and "modify" operations on "user", "computer" and
@@ -1056,10 +1009,7 @@ static int samldb_prim_group_change(struct samldb_ctx *ac)
 	struct ldb_dn *prev_prim_group_dn, *new_prim_group_dn;
 	int ret;
 
-	ret = samldb_get_single_valued_attr(ac, "primaryGroupID", &el);
-	if (ret != LDB_SUCCESS) {
-		return ret;
-	}
+	el = dsdb_get_single_valued_attr(ac->msg, "primaryGroupID");
 	if (el == NULL) {
 		/* we are not affected */
 		return LDB_SUCCESS;
@@ -1204,10 +1154,7 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac)
 	struct ldb_message *tmp_msg;
 	int ret;
 
-	ret = samldb_get_single_valued_attr(ac, "userAccountControl", &el);
-	if (ret != LDB_SUCCESS) {
-		return ret;
-	}
+	el = dsdb_get_single_valued_attr(ac->msg, "userAccountControl");
 	if (el == NULL) {
 		/* we are not affected */
 		return LDB_SUCCESS;
@@ -1280,10 +1227,7 @@ static int samldb_group_type_change(struct samldb_ctx *ac)
 	struct ldb_message *tmp_msg;
 	int ret;
 
-	ret = samldb_get_single_valued_attr(ac, "groupType", &el);
-	if (ret != LDB_SUCCESS) {
-		return ret;
-	}
+	el = dsdb_get_single_valued_attr(ac->msg, "groupType");
 	if (el == NULL) {
 		/* we are not affected */
 		return LDB_SUCCESS;
@@ -1369,10 +1313,7 @@ static int samldb_sam_accountname_check(struct samldb_ctx *ac)
 	struct ldb_message *tmp_msg;
 	int ret;
 
-	ret = samldb_get_single_valued_attr(ac, "sAMAccountName", &el);
-	if (ret != LDB_SUCCESS) {
-		return ret;
-	}
+	el = dsdb_get_single_valued_attr(ac->msg, "sAMAccountName");
 	if (el == NULL) {
 		/* we are not affected */
 		return LDB_SUCCESS;
@@ -1529,27 +1470,8 @@ static int samldb_service_principal_names_change(struct samldb_ctx *ac)
 	unsigned int i;
 	int ret;
 
-	/* Here it's not the same logic as with "samldb_get_single_valued_attr".
-	 * We need to:
-	 *
-	 * - consider "add" and "replace" operations - the last value we take
-	 * - ignore "delete" operations - obviously this attribute isn't
-	 *   write protected
-	 */
-	for (i = 0; i < ac->msg->num_elements; i++) {
-		if ((ldb_attr_cmp(ac->msg->elements[i].name,
-				  "dNSHostName") == 0) &&
-		    (LDB_FLAG_MOD_TYPE(ac->msg->elements[i].flags)
-				       != LDB_FLAG_MOD_DELETE)) {
-			el = &ac->msg->elements[i];
-		}
-		if ((ldb_attr_cmp(ac->msg->elements[i].name,
-				  "sAMAccountName") == 0) &&
-		    (LDB_FLAG_MOD_TYPE(ac->msg->elements[i].flags)
-				       != LDB_FLAG_MOD_DELETE)) {
-			el2 = &ac->msg->elements[i];
-		}
-	}
+	el = dsdb_get_single_valued_attr(ac->msg, "dNSHostName");
+	el2 = dsdb_get_single_valued_attr(ac->msg, "sAMAccountName");
 	if ((el == NULL) && (el2 == NULL)) {
 		/* we are not affected */
 		return LDB_SUCCESS;
diff --git a/source4/dsdb/samdb/ldb_modules/util.c b/source4/dsdb/samdb/ldb_modules/util.c
index e42bc77..7d6fcc4 100644
--- a/source4/dsdb/samdb/ldb_modules/util.c
+++ b/source4/dsdb/samdb/ldb_modules/util.c
@@ -1108,3 +1108,33 @@ void dsdb_req_chain_debug(struct ldb_request *req, int level)
 	DEBUG(level, ("%s\n", s));
 	talloc_free(s);
 }
+
+/*
+ * Gets back a single-valued attribute by the rules of the DSDB triggers when
+ * performing a modify operation.
+ *
+ * In order that the constraint checking by the "objectclass_attrs" LDB module
+ * does work properly, the change request should remain similar or only be
+ * enhanced (no other modifications as deletions, variations).
+ */
+struct ldb_message_element *dsdb_get_single_valued_attr(struct ldb_message *msg,
+							const char *attr_name)
+{
+	struct ldb_message_element *el = NULL;
+	unsigned int i;
+
+	/* We've to walk over all modification entries and consider the last
+	 * non-delete one which belongs to "attr_name".
+	 *
+	 * If "el" is NULL afterwards then that means there was no interesting
+	 * change entry. */
+	for (i = 0; i < msg->num_elements; i++) {
+		if ((ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) &&
+		    (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
+						!= LDB_FLAG_MOD_DELETE)) {
+			el = &msg->elements[i];
+		}
+	}
+
+	return el;
+}
diff --git a/source4/dsdb/tests/python/sam.py b/source4/dsdb/tests/python/sam.py
index 039ddf1..e1dbc6b 100755
--- a/source4/dsdb/tests/python/sam.py
+++ b/source4/dsdb/tests/python/sam.py
@@ -592,7 +592,7 @@ class SamTests(unittest.TestCase):
 
         m = Message()
         m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
-        m["groupType"] = MessageElement("0", FLAG_MOD_ADD,
+        m["groupType"] = MessageElement(str(GTYPE_SECURITY_GLOBAL_GROUP), FLAG_MOD_ADD,
           "groupType")
         try:
             ldb.modify(m)
@@ -612,7 +612,7 @@ class SamTests(unittest.TestCase):
 
         m = Message()
         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
-        m["primaryGroupID"] = MessageElement("0", FLAG_MOD_ADD,
+        m["primaryGroupID"] = MessageElement("513", FLAG_MOD_ADD,
           "primaryGroupID")
         try:
             ldb.modify(m)
@@ -632,7 +632,7 @@ class SamTests(unittest.TestCase):
 
         m = Message()
         m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
-        m["userAccountControl"] = MessageElement("0", FLAG_MOD_ADD,
+        m["userAccountControl"] = MessageElement(str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD), FLAG_MOD_ADD,
           "userAccountControl")
         try:
             ldb.modify(m)


-- 
Samba Shared Repository


More information about the samba-cvs mailing list