[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Thu Jan 22 02:17:02 MST 2015


The branch, master has been updated
       via  496b67b dsdb-tests: Clarify that accounts really do fall back to UF_NORMAL_ACCOUNT if no account set
       via  daeedb0 dsdb-samldb: Clarify userAccountControl manipulation code by always using UF_ flags
       via  1279d5e dsdb-samldb: Clarify that accounts really do fall back to UF_NORMAL_ACCOUNT if no account set
       via  49485ab dsdb-samldb: Only allow known and settable userAccountControl bits to be set
       via  ad98c0e dsdb-tests: Show that we can not change the primaryGroupID of a DC
       via  2a43275 s4:dsdb/samldb: let samldb_prim_group_change() protect DOMAIN_RID_{READONLY_,}DCS
       via  735605a dsdb: Improve userAccountControl handling
       via  bf99abb dsdb-tests: Add new test samba4.user_account_control.python
       via  b995ef3 dsdb: Default to UF_NORMAL_ACCOUNT when no account type is specified
       via  412b602 libds: UF_PARTIAL_SECRETS_ACCOUNT is a flag, not an account type
       via  7e41bcf dsdb-tests: Align sam.py with Windows 2012R2 and uncomment userAccountControl tests
      from  cde5d38 vfs:glusterfs: whitespace fix.

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


- Log -----------------------------------------------------------------
commit 496b67b27ab9856017a07b2fbcc5ba465f1945b3
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Tue Jan 6 16:49:14 2015 +1300

    dsdb-tests: Clarify that accounts really do fall back to UF_NORMAL_ACCOUNT if no account set
    
    Also confirm what bits have to be ignored, or otherwise processed
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=10993
    
    Pair-programmed-with: Garming Sam <garming at catalyst.net.nz>
    Signed-off-by: Garming Sam <garming at catalyst.net.nz>
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    
    Autobuild-User(master): Andrew Bartlett <abartlet at samba.org>
    Autobuild-Date(master): Thu Jan 22 10:16:42 CET 2015 on sn-devel-104

commit daeedb030fc019091332cbf3e8f6a2cc5d0d5273
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Tue Jan 6 16:48:40 2015 +1300

    dsdb-samldb: Clarify userAccountControl manipulation code by always using UF_ flags
    
    The use of ACB_ flags was required before msDS-User-Account-Control-Computed was implemented
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=10993
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit 1279d5e863d51fb03d84bfec51e9dc6a632fabd4
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Tue Jan 6 16:47:36 2015 +1300

    dsdb-samldb: Clarify that accounts really do fall back to UF_NORMAL_ACCOUNT if no account set
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=10993
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit 49485ab9782b7abc32581f29c35d862bb9a7058c
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Tue Jan 6 16:43:37 2015 +1300

    dsdb-samldb: Only allow known and settable userAccountControl bits to be set
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=10993
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Signed-off-by: Garming Sam <garming at catalyst.net.nz>
    Pair-programmed-with: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit ad98c0e1755e3fdc6efd8551590c1781b318a04f
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Wed Dec 10 15:54:11 2014 +1300

    dsdb-tests: Show that we can not change the primaryGroupID of a DC
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=10993
    
    Signed-off-by: Garming Sam <garming at catalyst.net.nz>
    Pair-programmed-with: Garming Sam <garming at catalyst.net.nz>
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit 2a432752c0eb8ef1ae395004ee1f0ba9b8ad88ba
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Apr 1 19:22:35 2014 +0200

    s4:dsdb/samldb: let samldb_prim_group_change() protect DOMAIN_RID_{READONLY_,}DCS
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=10993
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit 735605a6b0ad3ed98d46d1df920e64879a8c69cc
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Wed Dec 10 14:15:54 2014 +1300

    dsdb: Improve userAccountControl handling
    
    We now always check the ACL and invarient rules using the same function
    
    The change to libds is because UF_PARTIAL_SECRETS_ACCOUNT is a flag,
    not an account type
    
    This list should only be of the account exclusive account type bits.
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=10993
    
    Pair-programmed-with: Garming Sam <garming at catalyst.net.nz>
    Signed-off-by: Garming Sam <garming at catalyst.net.nz>
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit bf99abb5db91839d8e3589722fe9be000f857691
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Mon Dec 8 15:07:59 2014 +1300

    dsdb-tests: Add new test samba4.user_account_control.python
    
    This confirms security behaviour of the userAccountControl attribute
    as well as the behaviour on ADD as well as MODIFY, for every
    userAccountControl bit.
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=10993
    
    Change-Id: I8cd0e0b3c8d40e8b8aea844189703c756cc372f0
    Pair-programmed-with: Garming Sam <garming at catalyst.net.nz>
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Signed-off-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit b995ef3795511fadae3556e706e77abb39f8791c
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Wed Dec 10 14:26:28 2014 +1300

    dsdb: Default to UF_NORMAL_ACCOUNT when no account type is specified
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=10993
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit 412b602314e1174824d86940eacd74fb76774aba
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Wed Dec 10 14:15:54 2014 +1300

    libds: UF_PARTIAL_SECRETS_ACCOUNT is a flag, not an account type
    
    This list should only be of the account exclusive account type bits.
    
    Note, this corrects the behaviour in samldb modifies of
    userAccountControl.
    
    This reverts 6cb91a8f33516a33210a25e4019f3f3fbbfe61f2
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=10993
    
    Pair-programmed-with: Garming Sam <garming at catalyst.net.nz>
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Signed-off-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

commit 7e41bcf3053e147a6511071bd61f45db8e055165
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Mon Dec 8 14:31:42 2014 +1300

    dsdb-tests: Align sam.py with Windows 2012R2 and uncomment userAccountControl tests
    
    These tests now pass against Samba and Windows 2012R2.
    
    Bug: https://bugzilla.samba.org/show_bug.cgi?id=10993
    
    Change-Id: I1d7ba5e6a720b8da88c667bbbf3a4302c54642f4
    Pair-programmed-with: Garming Sam <garming at catalyst.net.nz>
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Signed-off-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>

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

Summary of changes:
 libds/common/flags.h                              |  20 +-
 source4/dsdb/samdb/ldb_modules/samldb.c           | 253 ++++++--
 source4/dsdb/tests/python/sam.py                  | 150 +++--
 source4/dsdb/tests/python/user_account_control.py | 699 ++++++++++++++++++++++
 source4/selftest/tests.py                         |   1 +
 5 files changed, 983 insertions(+), 140 deletions(-)
 create mode 100644 source4/dsdb/tests/python/user_account_control.py


Changeset truncated at 500 lines:

diff --git a/libds/common/flags.h b/libds/common/flags.h
index 4975024..f821e17 100644
--- a/libds/common/flags.h
+++ b/libds/common/flags.h
@@ -64,17 +64,21 @@
 		UF_NORMAL_ACCOUNT |\
 		UF_INTERDOMAIN_TRUST_ACCOUNT |\
 		UF_WORKSTATION_TRUST_ACCOUNT |\
-		UF_SERVER_TRUST_ACCOUNT |\
-		UF_PARTIAL_SECRETS_ACCOUNT \
+		UF_SERVER_TRUST_ACCOUNT \
                 )
 
+/*
+ * MS-SAMR 2.2.1.13 UF_FLAG Codes states that some bits are ignored by
+ * clients and servers.  Other flags (like UF_LOCKOUT have special
+ * behaviours, but are not set in the traditional sense).
+ *
+ * See the samldb module for the use of this define.
+ */
+
 #define UF_SETTABLE_BITS (\
-		UF_SCRIPT |\
 		UF_ACCOUNTDISABLE |\
 		UF_HOMEDIR_REQUIRED  |\
-		UF_LOCKOUT |\
 		UF_PASSWD_NOTREQD |\
-		UF_PASSWD_CANT_CHANGE |\
 		UF_ACCOUNT_TYPE_MASK | \
 		UF_DONT_EXPIRE_PASSWD | \
 		UF_MNS_LOGON_ACCOUNT |\
@@ -83,7 +87,11 @@
 		UF_TRUSTED_FOR_DELEGATION |\
 		UF_NOT_DELEGATED |\
 		UF_USE_DES_KEY_ONLY  |\
-		UF_DONT_REQUIRE_PREAUTH \
+		UF_DONT_REQUIRE_PREAUTH |\
+	        UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION |\
+	        UF_NO_AUTH_DATA_REQUIRED |\
+		UF_PARTIAL_SECRETS_ACCOUNT |\
+		UF_USE_AES_KEYS \
 		)
 
 /* Group flags for "groupType" */
diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c
index 54e2e5e..ade7c9a 100644
--- a/source4/dsdb/samdb/ldb_modules/samldb.c
+++ b/source4/dsdb/samdb/ldb_modules/samldb.c
@@ -945,10 +945,10 @@ static int samldb_schema_info_update(struct samldb_ctx *ac)
 }
 
 static int samldb_prim_group_tester(struct samldb_ctx *ac, uint32_t rid);
-static int samldb_check_user_account_control_acl(struct samldb_ctx *ac,
-						 struct dom_sid *sid,
-						 uint32_t user_account_control,
-						 uint32_t user_account_control_old);
+static int samldb_check_user_account_control_rules(struct samldb_ctx *ac,
+						   struct dom_sid *sid,
+						   uint32_t user_account_control,
+						   uint32_t user_account_control_old);
 
 /*
  * "Objectclass" trigger (MS-SAMR 3.1.1.8.1)
@@ -1048,9 +1048,13 @@ static int samldb_objectclass_trigger(struct samldb_ctx *ac)
 			user_account_control = ldb_msg_find_attr_as_uint(ac->msg,
 									 "userAccountControl",
 									 0);
-			/* "userAccountControl" = 0 means "UF_NORMAL_ACCOUNT" */
-			if (user_account_control == 0) {
-				user_account_control = UF_NORMAL_ACCOUNT;
+			/*
+			 * "userAccountControl" = 0 or missing one of
+			 * the types means "UF_NORMAL_ACCOUNT".  See
+			 * MS-SAMR 3.1.1.8.10 point 8
+			 */
+			if ((user_account_control & UF_ACCOUNT_TYPE_MASK) == 0) {
+				user_account_control = UF_NORMAL_ACCOUNT | user_account_control;
 				uac_generated = true;
 			}
 
@@ -1066,9 +1070,10 @@ static int samldb_objectclass_trigger(struct samldb_ctx *ac)
 				uac_generated = true;
 			}
 
-			/* Temporary duplicate accounts aren't allowed */
-			if ((user_account_control & UF_TEMP_DUPLICATE_ACCOUNT) != 0) {
-				return LDB_ERR_OTHER;
+			ret = samldb_check_user_account_control_rules(ac, NULL,
+								      user_account_control, 0);
+			if (ret != LDB_SUCCESS) {
+				return ret;
 			}
 
 			/* Workstation and (read-only) DC objects do need objectclass "computer" */
@@ -1160,11 +1165,6 @@ static int samldb_objectclass_trigger(struct samldb_ctx *ac)
 				}
 			}
 
-			ret = samldb_check_user_account_control_acl(ac, NULL,
-								    user_account_control, 0);
-			if (ret != LDB_SUCCESS) {
-				return ret;
-			}
 		}
 		break;
 	}
@@ -1289,11 +1289,15 @@ static int samldb_prim_group_set(struct samldb_ctx *ac)
 static int samldb_prim_group_change(struct samldb_ctx *ac)
 {
 	struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
-	const char * const attrs[] = { "primaryGroupID", "memberOf", NULL };
+	const char * const attrs[] = {
+		"primaryGroupID",
+		"memberOf",
+		"userAccountControl",
+		NULL };
 	struct ldb_result *res, *group_res;
 	struct ldb_message_element *el;
 	struct ldb_message *msg;
-	uint32_t prev_rid, new_rid;
+	uint32_t prev_rid, new_rid, uac;
 	struct dom_sid *prev_sid, *new_sid;
 	struct ldb_dn *prev_prim_group_dn, *new_prim_group_dn;
 	int ret;
@@ -1314,6 +1318,8 @@ static int samldb_prim_group_change(struct samldb_ctx *ac)
 		return ret;
 	}
 
+	uac = ldb_msg_find_attr_as_uint(res->msgs[0], "userAccountControl", 0);
+
 	/* Finds out the DN of the old primary group */
 
 	prev_rid = ldb_msg_find_attr_as_uint(res->msgs[0], "primaryGroupID",
@@ -1353,6 +1359,24 @@ static int samldb_prim_group_change(struct samldb_ctx *ac)
 		return LDB_SUCCESS;
 	}
 
+	if ((uac & UF_SERVER_TRUST_ACCOUNT) && new_rid != DOMAIN_RID_DCS) {
+		ldb_asprintf_errstring(ldb,
+			"%08X: samldb: UF_SERVER_TRUST_ACCOUNT requires "
+			"primaryGroupID=%u!",
+			W_ERROR_V(WERR_DS_CANT_MOD_PRIMARYGROUPID),
+			DOMAIN_RID_DCS);
+		return LDB_ERR_UNWILLING_TO_PERFORM;
+	}
+
+	if ((uac & UF_PARTIAL_SECRETS_ACCOUNT) && new_rid != DOMAIN_RID_READONLY_DCS) {
+		ldb_asprintf_errstring(ldb,
+			"%08X: samldb: UF_PARTIAL_SECRETS_ACCOUNT requires "
+			"primaryGroupID=%u!",
+			W_ERROR_V(WERR_DS_CANT_MOD_PRIMARYGROUPID),
+			DOMAIN_RID_READONLY_DCS);
+		return LDB_ERR_UNWILLING_TO_PERFORM;
+	}
+
 	ret = dsdb_module_search(ac->module, ac, &group_res,
 				 ldb_get_default_basedn(ldb),
 				 LDB_SCOPE_SUBTREE,
@@ -1452,6 +1476,110 @@ static int samldb_prim_group_trigger(struct samldb_ctx *ac)
 	return ret;
 }
 
+static int samldb_check_user_account_control_invariants(struct samldb_ctx *ac,
+						    uint32_t user_account_control)
+{
+	int i, ret = 0;
+	bool need_check = false;
+	const struct uac_to_guid {
+		uint32_t uac;
+		bool never;
+		uint32_t needs;
+		uint32_t not_with;
+		const char *error_string;
+	} map[] = {
+		{
+			.uac = UF_TEMP_DUPLICATE_ACCOUNT,
+			.never = true,
+			.error_string = "Updating the UF_TEMP_DUPLICATE_ACCOUNT flag is never allowed"
+		},
+		{
+			.uac = UF_PARTIAL_SECRETS_ACCOUNT,
+			.needs = UF_WORKSTATION_TRUST_ACCOUNT,
+			.error_string = "Setting UF_PARTIAL_SECRETS_ACCOUNT only permitted with UF_WORKSTATION_TRUST_ACCOUNT"
+		},
+		{
+			.uac = UF_TRUSTED_FOR_DELEGATION,
+			.not_with = UF_PARTIAL_SECRETS_ACCOUNT,
+			.error_string = "Setting UF_TRUSTED_FOR_DELEGATION not allowed with UF_PARTIAL_SECRETS_ACCOUNT"
+		},
+		{
+			.uac = UF_NORMAL_ACCOUNT,
+			.not_with = UF_ACCOUNT_TYPE_MASK & ~UF_NORMAL_ACCOUNT,
+			.error_string = "Setting more than one account type not permitted"
+		},
+		{
+			.uac = UF_WORKSTATION_TRUST_ACCOUNT,
+			.not_with = UF_ACCOUNT_TYPE_MASK & ~UF_WORKSTATION_TRUST_ACCOUNT,
+			.error_string = "Setting more than one account type not permitted"
+		},
+		{
+			.uac = UF_INTERDOMAIN_TRUST_ACCOUNT,
+			.not_with = UF_ACCOUNT_TYPE_MASK & ~UF_INTERDOMAIN_TRUST_ACCOUNT,
+			.error_string = "Setting more than one account type not permitted"
+		},
+		{
+			.uac = UF_SERVER_TRUST_ACCOUNT,
+			.not_with = UF_ACCOUNT_TYPE_MASK & ~UF_SERVER_TRUST_ACCOUNT,
+			.error_string = "Setting more than one account type not permitted"
+		},
+		{
+			.uac = UF_TRUSTED_FOR_DELEGATION,
+			.not_with = UF_PARTIAL_SECRETS_ACCOUNT,
+			.error_string = "Setting UF_TRUSTED_FOR_DELEGATION not allowed with UF_PARTIAL_SECRETS_ACCOUNT"
+		}
+	};
+
+	for (i = 0; i < ARRAY_SIZE(map); i++) {
+		if (user_account_control & map[i].uac) {
+			need_check = true;
+			break;
+		}
+	}
+	if (need_check == false) {
+		return LDB_SUCCESS;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(map); i++) {
+		uint32_t this_uac = user_account_control & map[i].uac;
+		if (this_uac != 0) {
+			if (map[i].never) {
+				ret = LDB_ERR_OTHER;
+				break;
+			} else if (map[i].needs != 0) {
+				if ((map[i].needs & user_account_control) == 0) {
+					ret = LDB_ERR_OTHER;
+					break;
+				}
+			} else if (map[i].not_with != 0) {
+				if ((map[i].not_with & user_account_control) != 0) {
+					ret = LDB_ERR_OTHER;
+					break;
+				}
+			}
+		}
+	}
+	if (ret != LDB_SUCCESS) {
+		switch (ac->req->operation) {
+		case LDB_ADD:
+			ldb_asprintf_errstring(ldb_module_get_ctx(ac->module),
+					       "Failed to add %s: %s",
+					       ldb_dn_get_linearized(ac->msg->dn),
+					       map[i].error_string);
+			break;
+		case LDB_MODIFY:
+			ldb_asprintf_errstring(ldb_module_get_ctx(ac->module),
+					       "Failed to modify %s: %s",
+					       ldb_dn_get_linearized(ac->msg->dn),
+					       map[i].error_string);
+			break;
+		default:
+			return ldb_module_operr(ac->module);
+		}
+	}
+	return ret;
+}
+
 /**
  * Validate that the restriction in point 5 of MS-SAMR 3.1.1.8.10 userAccountControl is honoured
  *
@@ -1619,6 +1747,24 @@ static int samldb_check_user_account_control_acl(struct samldb_ctx *ac,
 	return ret;
 }
 
+static int samldb_check_user_account_control_rules(struct samldb_ctx *ac,
+						   struct dom_sid *sid,
+						   uint32_t user_account_control,
+						   uint32_t user_account_control_old)
+{
+	int ret;
+	ret = samldb_check_user_account_control_invariants(ac, user_account_control);
+	if (ret != LDB_SUCCESS) {
+		return ret;
+	}
+	ret = samldb_check_user_account_control_acl(ac, sid, user_account_control, user_account_control_old);
+	if (ret != LDB_SUCCESS) {
+		return ret;
+	}
+	return ret;
+}
+
+
 /**
  * This function is called on LDB modify operations. It performs some additions/
  * replaces on the current LDB message when "userAccountControl" changes.
@@ -1631,9 +1777,8 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac)
 	uint32_t raw_uac;
 	uint32_t old_ufa;
 	uint32_t new_ufa;
-	uint32_t old_acb;
-	uint32_t new_acb;
-	uint32_t clear_acb;
+	uint32_t old_uac_computed;
+	uint32_t clear_uac;
 	uint32_t old_atype;
 	uint32_t new_atype;
 	uint32_t old_pgrid;
@@ -1680,15 +1825,19 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac)
 	raw_uac = ldb_msg_find_attr_as_uint(tmp_msg,
 					    "userAccountControl",
 					    0);
-	new_acb = samdb_result_acct_flags(tmp_msg, NULL);
 	talloc_free(tmp_msg);
 	/*
-	 * UF_LOCKOUT and UF_PASSWORD_EXPIRED are only generated
-	 * and not stored. We ignore them almost completely.
+	 * UF_LOCKOUT, UF_PASSWD_CANT_CHANGE and UF_PASSWORD_EXPIRED
+	 * are only generated and not stored. We ignore them almost
+	 * completely, along with unknown bits and UF_SCRIPT.
 	 *
-	 * The only exception is the resulting ACB_AUTOLOCK in clear_acb.
+	 * The only exception is ACB_AUTOLOCK, which features in
+	 * clear_acb when the bit is cleared in this modify operation.
+	 *
+	 * MS-SAMR 2.2.1.13 UF_FLAG Codes states that some bits are
+	 * ignored by clients and servers
 	 */
-	new_uac = raw_uac & ~(UF_LOCKOUT|UF_PASSWORD_EXPIRED);
+	new_uac = raw_uac & UF_SETTABLE_BITS;
 
 	/* Fetch the old "userAccountControl" and "objectClass" */
 	ret = dsdb_module_search_dn(ac->module, ac, &res, ac->msg->dn, attrs,
@@ -1700,8 +1849,8 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac)
 	if (old_uac == 0) {
 		return ldb_operr(ldb);
 	}
-	old_acb = samdb_result_acct_flags(res->msgs[0],
-					  "msDS-User-Account-Control-Computed");
+	old_uac_computed = ldb_msg_find_attr_as_uint(res->msgs[0],
+						     "msDS-User-Account-Control-Computed", 0);
 	old_lockoutTime = ldb_msg_find_attr_as_int64(res->msgs[0],
 						     "lockoutTime", 0);
 	old_is_critical = ldb_msg_find_attr_as_bool(res->msgs[0],
@@ -1724,16 +1873,27 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac)
 	new_ufa = new_uac & UF_ACCOUNT_TYPE_MASK;
 	if (new_ufa == 0) {
 		/*
-		 * When there is no account type embedded in "userAccountControl"
-		 * fall back to the old.
+		 * "userAccountControl" = 0 or missing one of the
+		 * types means "UF_NORMAL_ACCOUNT".  See MS-SAMR
+		 * 3.1.1.8.10 point 8
 		 */
-		new_ufa = old_ufa;
+		new_ufa = UF_NORMAL_ACCOUNT;
 		new_uac |= new_ufa;
 	}
+	sid = samdb_result_dom_sid(res, res->msgs[0], "objectSid");
+	if (sid == NULL) {
+		return ldb_module_operr(ac->module);
+	}
+
+	ret = samldb_check_user_account_control_rules(ac, sid, new_uac, old_uac);
+	if (ret != LDB_SUCCESS) {
+		return ret;
+	}
+
 	new_atype = ds_uf2atype(new_ufa);
 	new_pgrid = ds_uf2prim_group_rid(new_uac);
 
-	clear_acb = old_acb & ~new_acb;
+	clear_uac = (old_uac | old_uac_computed) & ~raw_uac;
 
 	switch (new_ufa) {
 	case UF_NORMAL_ACCOUNT:
@@ -1746,17 +1906,16 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac)
 
 	case UF_WORKSTATION_TRUST_ACCOUNT:
 		new_is_critical = false;
-		break;
-
-	case (UF_WORKSTATION_TRUST_ACCOUNT|UF_PARTIAL_SECRETS_ACCOUNT):
-		if (!is_computer) {
-			ldb_asprintf_errstring(ldb,
-				"%08X: samldb: UF_PARTIAL_SECRETS_ACCOUNT "
-				"requires objectclass 'computer'!",
-				W_ERROR_V(WERR_DS_MACHINE_ACCOUNT_CREATED_PRENT4));
-			return LDB_ERR_UNWILLING_TO_PERFORM;
+		if (new_uac & UF_PARTIAL_SECRETS_ACCOUNT) {
+			if (!is_computer) {
+				ldb_asprintf_errstring(ldb,
+						       "%08X: samldb: UF_PARTIAL_SECRETS_ACCOUNT "
+						       "requires objectclass 'computer'!",
+						       W_ERROR_V(WERR_DS_MACHINE_ACCOUNT_CREATED_PRENT4));
+				return LDB_ERR_UNWILLING_TO_PERFORM;
+			}
+			new_is_critical = true;
 		}
-		new_is_critical = true;
 		break;
 
 	case UF_SERVER_TRUST_ACCOUNT:
@@ -1788,7 +1947,7 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac)
 	}
 
 	/* As per MS-SAMR 3.1.1.8.10 these flags have not to be set */
-	if ((clear_acb & ACB_AUTOLOCK) && (old_lockoutTime != 0)) {
+	if ((clear_uac & UF_LOCKOUT) && (old_lockoutTime != 0)) {
 		/* "pwdLastSet" reset as password expiration has been forced  */
 		ldb_msg_remove_attr(ac->msg, "lockoutTime");
 		ret = samdb_msg_add_uint64(ldb, ac->msg, ac->msg, "lockoutTime",
@@ -1849,16 +2008,6 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac)
 		ldb_msg_remove_attr(ac->msg, "userAccountControl");
 	}
 
-	sid = samdb_result_dom_sid(res, res->msgs[0], "objectSid");
-	if (sid == NULL) {
-		return ldb_module_operr(ac->module);
-	}
-
-	ret = samldb_check_user_account_control_acl(ac, sid, new_uac, old_uac);
-	if (ret != LDB_SUCCESS) {
-		return ret;
-	}
-
 	return LDB_SUCCESS;
 }
 
diff --git a/source4/dsdb/tests/python/sam.py b/source4/dsdb/tests/python/sam.py
index 31b5a39..25da8f9 100755
--- a/source4/dsdb/tests/python/sam.py
+++ b/source4/dsdb/tests/python/sam.py
@@ -22,12 +22,14 @@ from ldb import ERR_OTHER, ERR_NO_SUCH_ATTRIBUTE
 from ldb import ERR_OBJECT_CLASS_VIOLATION
 from ldb import ERR_CONSTRAINT_VIOLATION
 from ldb import ERR_UNDEFINED_ATTRIBUTE_TYPE
+from ldb import ERR_INSUFFICIENT_ACCESS_RIGHTS
 from ldb import Message, MessageElement, Dn
 from ldb import FLAG_MOD_ADD, FLAG_MOD_REPLACE, FLAG_MOD_DELETE
 from samba.samdb import SamDB
 from samba.dsdb import (UF_NORMAL_ACCOUNT, UF_ACCOUNTDISABLE,
     UF_WORKSTATION_TRUST_ACCOUNT, UF_SERVER_TRUST_ACCOUNT,
     UF_PARTIAL_SECRETS_ACCOUNT, UF_TEMP_DUPLICATE_ACCOUNT,
+    UF_INTERDOMAIN_TRUST_ACCOUNT,
     UF_PASSWD_NOTREQD, UF_LOCKOUT, UF_PASSWORD_EXPIRED, ATYPE_NORMAL_ACCOUNT,
     GTYPE_SECURITY_BUILTIN_LOCAL_GROUP, GTYPE_SECURITY_DOMAIN_LOCAL_GROUP,
     GTYPE_SECURITY_GLOBAL_GROUP, GTYPE_SECURITY_UNIVERSAL_GROUP,
@@ -1440,16 +1442,11 @@ class SamTests(samba.tests.TestCase):
         self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_PASSWD_NOTREQD == 0)
         delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
 
-# This has to wait until s4 supports it (needs a password module change)
-#        try:
-#            ldb.add({
-#                "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
-#                "objectclass": "user",
-#                "userAccountControl": str(UF_NORMAL_ACCOUNT)})
-#            self.fail()
-#        except LdbError, (num, _):
-#            self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
-#        delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
+        ldb.add({
+            "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
+            "objectclass": "user",
+            "userAccountControl": str(UF_NORMAL_ACCOUNT)})
+        delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
 
         ldb.add({
             "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
@@ -1519,16 +1516,15 @@ class SamTests(samba.tests.TestCase):
             self.assertEquals(num, ERR_OBJECT_CLASS_VIOLATION)
         delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
 
-# This isn't supported yet in s4 - needs ACL module adaption
-#        try:
-#            ldb.add({
-#                "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
-#                "objectclass": "user",
-#                "userAccountControl": str(UF_INTERDOMAIN_TRUST_ACCOUNT)})
-#            self.fail()
-#        except LdbError, (num, _):
-#            self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
-#        delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
+        try:
+            ldb.add({
+                "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
+                "objectclass": "user",
+                "userAccountControl": str(UF_INTERDOMAIN_TRUST_ACCOUNT)})
+            self.fail()
+        except LdbError, (num, _):
+            self.assertEquals(num, ERR_INSUFFICIENT_ACCESS_RIGHTS)
+        delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
 
         # Modify operation
 
@@ -1561,16 +1557,15 @@ class SamTests(samba.tests.TestCase):
         except LdbError, (num, _):
             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
 
-# This has to wait until s4 supports it (needs a password module change)
-#        try:


-- 
Samba Shared Repository


More information about the samba-cvs mailing list