[SCM] Samba Shared Repository - branch master updated

Matthias Dieter Wallnöfer mdw at samba.org
Sat Oct 30 13:08:01 MDT 2010


The branch, master has been updated
       via  9401189 s4:samldb LDB module - make the "userAccountControl" and "groupType" modify handlers separate functions
       via  098ea71 s4:samldb LDB module - add a new function which handles special cases for single-valued attribute on SAM modifications
       via  095c8b2 s4:samldb LDB module - primary group change - free temporary messages to save memory
      from  c0ebf5d s4:sam.py - add a short double swap "primaryGroupID" test

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


- Log -----------------------------------------------------------------
commit 9401189d5435632bcc6a177845ce03beaa804113
Author: Matthias Dieter Wallnöfer <mdw at samba.org>
Date:   Sat Oct 30 19:56:54 2010 +0200

    s4:samldb LDB module - make the "userAccountControl" and "groupType" modify handlers separate functions
    
    It's easier to maintain afterwards
    
    Autobuild-User: Matthias Dieter Wallnöfer <mdw at samba.org>
    Autobuild-Date: Sat Oct 30 19:07:20 UTC 2010 on sn-devel-104

commit 098ea71728eb6389ff4c5314d17df533f79a07a8
Author: Matthias Dieter Wallnöfer <mdw at samba.org>
Date:   Sat Oct 30 19:37:30 2010 +0200

    s4:samldb LDB module - add a new function which handles special cases for single-valued attribute on SAM modifications
    
    This saves quiet some work.

commit 095c8b2078128838f6b830613e80cbdcf49e10cf
Author: Matthias Dieter Wallnöfer <mdw at samba.org>
Date:   Sat Oct 30 19:56:24 2010 +0200

    s4:samldb LDB module - primary group change - free temporary messages to save memory

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

Summary of changes:
 source4/dsdb/samdb/ldb_modules/samldb.c |  380 ++++++++++++++++++------------
 1 files changed, 228 insertions(+), 152 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c
index 44c8fee..9b6d6e0 100644
--- a/source4/dsdb/samdb/ldb_modules/samldb.c
+++ b/source4/dsdb/samdb/ldb_modules/samldb.c
@@ -751,6 +751,53 @@ 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
@@ -1002,41 +1049,17 @@ static int samldb_prim_group_change(struct samldb_ctx *ac)
 	uint32_t rid;
 	struct dom_sid *sid;
 	struct ldb_dn *prev_prim_group_dn, *new_prim_group_dn;
-	unsigned int i;
 	int ret;
 
-	/* We've to walk over all modification entries and consider the
-	 * "primaryGroupID" 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.
-	 */
-	el = NULL;
-	for (i = 0; i < ac->msg->num_elements; i++) {
-		if (ldb_attr_cmp(ac->msg->elements[i].name,
-				 "primaryGroupID") != 0) {
-			continue;
-		}
-
-		el = &ac->msg->elements[i];
-		if (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_ADD) {
-			return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
-		}
-		if (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE) {
-			return LDB_ERR_UNWILLING_TO_PERFORM;
-		}
+	ret = samldb_get_single_valued_attr(ac, "primaryGroupID", &el);
+	if (ret != LDB_SUCCESS) {
+		return ret;
 	}
 	if (el == NULL) {
+		/* we are not affected */
 		return LDB_SUCCESS;
 	}
 
-	/* Okay, now for sure we are performing a "primaryGroupID" replace */
-
 	/* Fetch informations from the existing object */
 
 	ret = ldb_search(ldb, ac, &res, ac->msg->dn, LDB_SCOPE_BASE, attrs,
@@ -1109,7 +1132,7 @@ static int samldb_prim_group_change(struct samldb_ctx *ac)
 		}
 
 		/* Remove the "member" attribute on the new primary group */
-		msg = talloc_zero(ac, struct ldb_message);
+		msg = ldb_msg_new(ac->msg);
 		if (msg == NULL) {
 			return ldb_module_oom(ac->module);
 		}
@@ -1125,9 +1148,10 @@ static int samldb_prim_group_change(struct samldb_ctx *ac)
 		if (ret != LDB_SUCCESS) {
 			return ret;
 		}
+		talloc_free(msg);
 
 		/* Add a "member" attribute for the previous primary group */
-		msg = talloc_zero(ac, struct ldb_message);
+		msg = ldb_msg_new(ac->msg);
 		if (msg == NULL) {
 			return ldb_module_oom(ac->module);
 		}
@@ -1143,6 +1167,7 @@ static int samldb_prim_group_change(struct samldb_ctx *ac)
 		if (ret != LDB_SUCCESS) {
 			return ret;
 		}
+		talloc_free(msg);
 	}
 
 	talloc_free(res);
@@ -1163,6 +1188,169 @@ static int samldb_prim_group_trigger(struct samldb_ctx *ac)
 	return ret;
 }
 
+static int samldb_user_account_control_change(struct samldb_ctx *ac)
+{
+	struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
+	uint32_t user_account_control, account_type;
+	struct ldb_message_element *el;
+	struct ldb_message *tmp_msg;
+	int ret;
+
+	ret = samldb_get_single_valued_attr(ac, "userAccountControl", &el);
+	if (ret != LDB_SUCCESS) {
+		return ret;
+	}
+	if (el == NULL) {
+		/* we are not affected */
+		return LDB_SUCCESS;
+	}
+
+	/* Create a temporary message for fetching the "userAccountControl" */
+	tmp_msg = ldb_msg_new(ac->msg);
+	if (tmp_msg == NULL) {
+		return ldb_module_oom(ac->module);
+	}
+	ret = ldb_msg_add(tmp_msg, el, 0);
+	if (ret != LDB_SUCCESS) {
+		return ret;
+	}
+	user_account_control = ldb_msg_find_attr_as_uint(tmp_msg,
+							 "userAccountControl",
+							 0);
+	talloc_free(tmp_msg);
+
+	/* Temporary duplicate accounts aren't allowed */
+	if ((user_account_control & UF_TEMP_DUPLICATE_ACCOUNT) != 0) {
+		return LDB_ERR_OTHER;
+	}
+
+	account_type = ds_uf2atype(user_account_control);
+	if (account_type == 0) {
+		ldb_set_errstring(ldb, "samldb: Unrecognized account type!");
+		return LDB_ERR_UNWILLING_TO_PERFORM;
+	}
+	ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, "sAMAccountType",
+				 account_type);
+	if (ret != LDB_SUCCESS) {
+		return ret;
+	}
+	el = ldb_msg_find_element(ac->msg, "sAMAccountType");
+	el->flags = LDB_FLAG_MOD_REPLACE;
+
+	if (user_account_control
+	    & (UF_SERVER_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT)) {
+		ret = samdb_msg_add_string(ldb, ac->msg, ac->msg,
+					   "isCriticalSystemObject", "TRUE");
+		if (ret != LDB_SUCCESS) {
+			return ret;
+		}
+		el = ldb_msg_find_element(ac->msg,
+					   "isCriticalSystemObject");
+		el->flags = LDB_FLAG_MOD_REPLACE;
+	}
+
+	if (!ldb_msg_find_element(ac->msg, "primaryGroupID")) {
+		uint32_t rid = ds_uf2prim_group_rid(user_account_control);
+		ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
+					 "primaryGroupID", rid);
+		if (ret != LDB_SUCCESS) {
+			return ret;
+		}
+		el = ldb_msg_find_element(ac->msg,
+					   "primaryGroupID");
+		el->flags = LDB_FLAG_MOD_REPLACE;
+	}
+
+	return LDB_SUCCESS;
+}
+
+static int samldb_group_type_change(struct samldb_ctx *ac)
+{
+	struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
+	uint32_t group_type, old_group_type, account_type;
+	struct ldb_message_element *el;
+	struct ldb_message *tmp_msg;
+	int ret;
+
+	ret = samldb_get_single_valued_attr(ac, "groupType", &el);
+	if (ret != LDB_SUCCESS) {
+		return ret;
+	}
+	if (el == NULL) {
+		/* we are not affected */
+		return LDB_SUCCESS;
+	}
+
+	/* Create a temporary message for fetching the "groupType" */
+	tmp_msg = ldb_msg_new(ac->msg);
+	if (tmp_msg == NULL) {
+		return ldb_module_oom(ac->module);
+	}
+	ret = ldb_msg_add(tmp_msg, el, 0);
+	if (ret != LDB_SUCCESS) {
+		return ret;
+	}
+	group_type = ldb_msg_find_attr_as_uint(tmp_msg, "groupType", 0);
+	talloc_free(tmp_msg);
+
+	old_group_type = samdb_search_uint(ldb, ac, 0, ac->msg->dn,
+					   "groupType", NULL);
+	if (old_group_type == 0) {
+		return ldb_operr(ldb);
+	}
+
+	/* Group type switching isn't so easy as it seems: We can only
+	 * change in this directions: global <-> universal <-> local
+	 * On each step also the group type itself
+	 * (security/distribution) is variable. */
+
+	switch (group_type) {
+	case GTYPE_SECURITY_GLOBAL_GROUP:
+	case GTYPE_DISTRIBUTION_GLOBAL_GROUP:
+		/* change to "universal" allowed */
+		if ((old_group_type == GTYPE_SECURITY_DOMAIN_LOCAL_GROUP) ||
+		    (old_group_type == GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)) {
+			return LDB_ERR_UNWILLING_TO_PERFORM;
+		}
+	break;
+
+	case GTYPE_SECURITY_UNIVERSAL_GROUP:
+	case GTYPE_DISTRIBUTION_UNIVERSAL_GROUP:
+		/* each change allowed */
+	break;
+
+	case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
+	case GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP:
+		/* change to "universal" allowed */
+		if ((old_group_type == GTYPE_SECURITY_GLOBAL_GROUP) ||
+		    (old_group_type == GTYPE_DISTRIBUTION_GLOBAL_GROUP)) {
+			return LDB_ERR_UNWILLING_TO_PERFORM;
+		}
+	break;
+
+	case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
+	default:
+		/* we don't allow this "groupType" values */
+		return LDB_ERR_UNWILLING_TO_PERFORM;
+	break;
+	}
+
+	account_type =  ds_gtype2atype(group_type);
+	if (account_type == 0) {
+		ldb_set_errstring(ldb, "samldb: Unrecognized account type!");
+		return LDB_ERR_UNWILLING_TO_PERFORM;
+	}
+	ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, "sAMAccountType",
+				 account_type);
+	if (ret != LDB_SUCCESS) {
+		return ret;
+	}
+	el = ldb_msg_find_element(ac->msg, "sAMAccountType");
+	el->flags = LDB_FLAG_MOD_REPLACE;
+
+	return LDB_SUCCESS;
+}
+
 static int samldb_member_check(struct samldb_ctx *ac)
 {
 	struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
@@ -1354,10 +1542,9 @@ static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
 {
 	struct ldb_context *ldb;
 	struct samldb_ctx *ac;
-	struct ldb_message_element *el, *el2;
+	struct ldb_message_element *el;
 	bool modified = false;
 	int ret;
-	uint32_t account_type;
 
 	if (ldb_dn_is_special(req->op.mod.message->dn)) {
 		/* do not manipulate our control entries */
@@ -1406,75 +1593,6 @@ static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
 		return ldb_operr(ldb);
 	}
 
-	el = ldb_msg_find_element(ac->msg, "groupType");
-	if (el && (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_REPLACE)
-	    && el->num_values == 1) {
-		uint32_t group_type, old_group_type;
-
-		modified = true;
-
-		group_type = ldb_msg_find_attr_as_uint(ac->msg, "groupType", 0);
-		old_group_type = samdb_search_uint(ldb, ac, 0, ac->msg->dn,
-						   "groupType", NULL);
-		if (old_group_type == 0) {
-			return ldb_operr(ldb);
-		}
-
-		/* Group type switching isn't so easy as it seems: We can only
-		 * change in this directions: global <-> universal <-> local
-		 * On each step also the group type itself
-		 * (security/distribution) is variable. */
-
-		switch (group_type) {
-		case GTYPE_SECURITY_GLOBAL_GROUP:
-		case GTYPE_DISTRIBUTION_GLOBAL_GROUP:
-			/* change to "universal" allowed */
-			if ((old_group_type == GTYPE_SECURITY_DOMAIN_LOCAL_GROUP) ||
-			    (old_group_type == GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)) {
-				return LDB_ERR_UNWILLING_TO_PERFORM;
-			}
-		break;
-
-		case GTYPE_SECURITY_UNIVERSAL_GROUP:
-		case GTYPE_DISTRIBUTION_UNIVERSAL_GROUP:
-			/* each change allowed */
-		break;
-
-		case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
-		case GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP:
-			/* change to "universal" allowed */
-			if ((old_group_type == GTYPE_SECURITY_GLOBAL_GROUP) ||
-			    (old_group_type == GTYPE_DISTRIBUTION_GLOBAL_GROUP)) {
-				return LDB_ERR_UNWILLING_TO_PERFORM;
-			}
-		break;
-
-		case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
-		default:
-			/* we don't allow this "groupType" values */
-			return LDB_ERR_UNWILLING_TO_PERFORM;
-		break;
-		}
-
-		account_type =  ds_gtype2atype(group_type);
-		if (account_type == 0) {
-			ldb_set_errstring(ldb, "samldb: Unrecognized account type!");
-			return LDB_ERR_UNWILLING_TO_PERFORM;
-		}
-		ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
-					 "sAMAccountType",
-					 account_type);
-		if (ret != LDB_SUCCESS) {
-			return ret;
-		}
-		el2 = ldb_msg_find_element(ac->msg, "sAMAccountType");
-		el2->flags = LDB_FLAG_MOD_REPLACE;
-	}
-	el = ldb_msg_find_element(ac->msg, "groupType");
-	if (el && (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE)) {
-		return LDB_ERR_UNWILLING_TO_PERFORM;
-	}
-
 	el = ldb_msg_find_element(ac->msg, "primaryGroupID");
 	if (el != NULL) {
 		ret = samldb_prim_group_change(ac);
@@ -1484,64 +1602,22 @@ static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
 	}
 
 	el = ldb_msg_find_element(ac->msg, "userAccountControl");
-	if (el && (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_REPLACE)
-	    && el->num_values == 1) {
-		uint32_t user_account_control;
-
+	if (el != NULL) {
 		modified = true;
-
-		user_account_control = ldb_msg_find_attr_as_uint(ac->msg,
-								 "userAccountControl",
-								 0);
-
-		/* Temporary duplicate accounts aren't allowed */
-		if ((user_account_control & UF_TEMP_DUPLICATE_ACCOUNT) != 0) {
-			return LDB_ERR_OTHER;
-		}
-
-		account_type = ds_uf2atype(user_account_control);
-		if (account_type == 0) {
-			ldb_set_errstring(ldb, "samldb: Unrecognized account type!");
-			return LDB_ERR_UNWILLING_TO_PERFORM;
-		}
-		ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
-					 "sAMAccountType",
-					 account_type);
+		ret = samldb_user_account_control_change(ac);
 		if (ret != LDB_SUCCESS) {
 			return ret;
 		}
-		el2 = ldb_msg_find_element(ac->msg, "sAMAccountType");
-		el2->flags = LDB_FLAG_MOD_REPLACE;
-
-		if (user_account_control & (UF_SERVER_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT)) {
-			ret = samdb_msg_add_string(ldb, ac->msg, ac->msg,
-						   "isCriticalSystemObject",
-						   "TRUE");
-			if (ret != LDB_SUCCESS) {
-				return ret;
-			}
-			el2 = ldb_msg_find_element(ac->msg,
-						   "isCriticalSystemObject");
-			el2->flags = LDB_FLAG_MOD_REPLACE;
-		}
-
-		if (!ldb_msg_find_element(ac->msg, "primaryGroupID")) {
-			uint32_t rid = ds_uf2prim_group_rid(user_account_control);
+	}
 
-			ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
-						 "primaryGroupID", rid);
-			if (ret != LDB_SUCCESS) {
-				return ret;
-			}
-			el2 = ldb_msg_find_element(ac->msg,
-						   "primaryGroupID");
-			el2->flags = LDB_FLAG_MOD_REPLACE;
+	el = ldb_msg_find_element(ac->msg, "groupType");
+	if (el != NULL) {
+		modified = true;
+		ret = samldb_group_type_change(ac);
+		if (ret != LDB_SUCCESS) {
+			return ret;
 		}
 	}
-	el = ldb_msg_find_element(ac->msg, "userAccountControl");
-	if (el && (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE)) {
-		return LDB_ERR_UNWILLING_TO_PERFORM;
-	}
 
 	el = ldb_msg_find_element(ac->msg, "member");
 	if (el != NULL) {


-- 
Samba Shared Repository


More information about the samba-cvs mailing list