[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Sun Jun 9 23:33:02 MDT 2013


The branch, master has been updated
       via  7f760ed s4:samldb LDB module - MS-SAMR 3.1.1.8.10 "userAccountControl"
       via  2f7d9fd s4:samr RPC server - dcesrv_samr_SetUserInfo() - password expiration
      from  036af07 .gitignore: Tidy up after removal of the autoconf build

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


- Log -----------------------------------------------------------------
commit 7f760ed84b4b34937b3a65577f971cc95f452e0f
Author: Matthias Dieter Wallnöfer <mdw at samba.org>
Date:   Sat Jun 8 23:45:43 2013 +0200

    s4:samldb LDB module - MS-SAMR 3.1.1.8.10 "userAccountControl"
    
    "UF_LOCKOUT" and "UF_PASSWORD_EXPIRED" are never stored but rather are
    used for special semantics.
    "UF_LOCKOUT" performs an account lockout and "UF_PASSWORD_EXPIRED"
    forces password expiration.
    
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    
    Autobuild-User(master): Andrew Bartlett <abartlet at samba.org>
    Autobuild-Date(master): Mon Jun 10 07:32:35 CEST 2013 on sn-devel-104

commit 2f7d9fddf7102d76b182fbd50ccaf18cb5a10014
Author: Matthias Dieter Wallnöfer <mdw at samba.org>
Date:   Sun Jun 9 10:46:06 2013 +0200

    s4:samr RPC server - dcesrv_samr_SetUserInfo() - password expiration
    
    Also on level 26 this has to be handled the same as on levels 21, 23, 25.
    
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

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

Summary of changes:
 source4/dsdb/samdb/ldb_modules/samldb.c |   82 +++++++++++++++++++++++++------
 source4/dsdb/tests/python/sam.py        |   82 ++++++++++++++++++++++++++++++-
 source4/rpc_server/samr/dcesrv_samr.c   |    8 +++-
 3 files changed, 154 insertions(+), 18 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 5bb0b61..603370f 100644
--- a/source4/dsdb/samdb/ldb_modules/samldb.c
+++ b/source4/dsdb/samdb/ldb_modules/samldb.c
@@ -1049,6 +1049,18 @@ static int samldb_objectclass_trigger(struct samldb_ctx *ac)
 				uac_generated = true;
 			}
 
+			/*
+			 * As per MS-SAMR 3.1.1.8.10 these flags have not to be set
+			 */
+			if ((user_account_control & UF_LOCKOUT) != 0) {
+				user_account_control &= ~UF_LOCKOUT;
+				uac_generated = true;
+			}
+			if ((user_account_control & UF_PASSWORD_EXPIRED) != 0) {
+				user_account_control &= ~UF_PASSWORD_EXPIRED;
+				uac_generated = true;
+			}
+
 			/* Temporary duplicate accounts aren't allowed */
 			if ((user_account_control & UF_TEMP_DUPLICATE_ACCOUNT) != 0) {
 				return LDB_ERR_OTHER;
@@ -1442,9 +1454,10 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac)
 	struct ldb_message *tmp_msg;
 	int ret;
 	struct ldb_result *res;
-	const char * const attrs[] = { "userAccountControl", "objectClass", NULL };
+	const char * const attrs[] = { "userAccountControl", "objectClass",
+				       "lockoutTime", NULL };
 	unsigned int i;
-	bool is_computer = false;
+	bool is_computer = false, uac_generated = false;
 
 	el = dsdb_get_single_valued_attr(ac->msg, "userAccountControl",
 					 ac->req->operation);
@@ -1517,8 +1530,6 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac)
 
 	account_type = ds_uf2atype(user_account_control);
 	if (account_type == 0) {
-		char *tempstr;
-
 		/*
 		 * When there is no account type embedded in "userAccountControl"
 		 * fall back to default "UF_NORMAL_ACCOUNT".
@@ -1530,18 +1541,7 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac)
 		}
 
 		user_account_control |= UF_NORMAL_ACCOUNT;
-
-		tempstr = talloc_asprintf(ac->msg, "%d", user_account_control);
-		if (tempstr == NULL) {
-			return ldb_module_oom(ac->module);
-		}
-
-		/* Overwrite "userAccountControl" with "UF_NORMAL_ACCOUNT" added */
-		el = dsdb_get_single_valued_attr(ac->msg, "userAccountControl",
-						 ac->req->operation);
-		el->values[0].data = (uint8_t *) tempstr;
-		el->values[0].length = strlen(tempstr);
-
+		uac_generated = true;
 		account_type = ATYPE_NORMAL_ACCOUNT;
 	}
 	ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, "sAMAccountType",
@@ -1552,6 +1552,41 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac)
 	el = ldb_msg_find_element(ac->msg, "sAMAccountType");
 	el->flags = LDB_FLAG_MOD_REPLACE;
 
+	/* As per MS-SAMR 3.1.1.8.10 these flags have not to be set */
+	if ((user_account_control & UF_LOCKOUT) != 0) {
+		/* "lockoutTime" reset as per MS-SAMR 3.1.1.8.10 */
+		uint64_t lockout_time = ldb_msg_find_attr_as_uint64(res->msgs[0],
+								    "lockoutTime",
+								    0);
+		if (lockout_time != 0) {
+			ldb_msg_remove_attr(ac->msg, "lockoutTime");
+			ret = samdb_msg_add_uint64(ldb, ac->msg, ac->msg,
+						   "lockoutTime", (NTTIME)0);
+			if (ret != LDB_SUCCESS) {
+				return ret;
+			}
+			el = ldb_msg_find_element(ac->msg, "lockoutTime");
+			el->flags = LDB_FLAG_MOD_REPLACE;
+		}
+
+		user_account_control &= ~UF_LOCKOUT;
+		uac_generated = true;
+	}
+	if ((user_account_control & UF_PASSWORD_EXPIRED) != 0) {
+		/* "pwdLastSet" reset as password expiration has been forced  */
+		ldb_msg_remove_attr(ac->msg, "pwdLastSet");
+		ret = samdb_msg_add_uint64(ldb, ac->msg, ac->msg, "pwdLastSet",
+					   (NTTIME)0);
+		if (ret != LDB_SUCCESS) {
+			return ret;
+		}
+		el = ldb_msg_find_element(ac->msg, "pwdLastSet");
+		el->flags = LDB_FLAG_MOD_REPLACE;
+
+		user_account_control &= ~UF_PASSWORD_EXPIRED;
+		uac_generated = true;
+	}
+
 	/* "isCriticalSystemObject" might be set/changed */
 	if (user_account_control
 	    & (UF_SERVER_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT)) {
@@ -1595,6 +1630,21 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac)
 		el->flags = LDB_FLAG_MOD_REPLACE;
 	}
 
+	/* Propagate eventual "userAccountControl" attribute changes */
+	if (uac_generated) {
+		char *tempstr = talloc_asprintf(ac->msg, "%d",
+						user_account_control);
+		if (tempstr == NULL) {
+			return ldb_module_oom(ac->module);
+		}
+
+		/* Overwrite "userAccountControl" correctly */
+		el = dsdb_get_single_valued_attr(ac->msg, "userAccountControl",
+						 ac->req->operation);
+		el->values[0].data = (uint8_t *) tempstr;
+		el->values[0].length = strlen(tempstr);
+	}
+
 	return LDB_SUCCESS;
 }
 
diff --git a/source4/dsdb/tests/python/sam.py b/source4/dsdb/tests/python/sam.py
index 361a108..754096a 100755
--- a/source4/dsdb/tests/python/sam.py
+++ b/source4/dsdb/tests/python/sam.py
@@ -27,7 +27,7 @@ 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_PASSWD_NOTREQD, ATYPE_NORMAL_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,
     GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP, GTYPE_DISTRIBUTION_GLOBAL_GROUP,
@@ -1465,6 +1465,22 @@ class SamTests(samba.tests.TestCase):
         self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE == 0)
         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 | UF_PASSWD_NOTREQD | UF_LOCKOUT | UF_PASSWORD_EXPIRED)})
+
+        res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
+                          scope=SCOPE_BASE,
+                          attrs=["sAMAccountType", "userAccountControl", "lockoutTime", "pwdLastSet"])
+        self.assertTrue(len(res1) == 1)
+        self.assertEquals(int(res1[0]["sAMAccountType"][0]),
+          ATYPE_NORMAL_ACCOUNT)
+        self.assertTrue(int(res1[0]["userAccountControl"][0]) & (UF_LOCKOUT | UF_PASSWORD_EXPIRED) == 0)
+        self.assertFalse("lockoutTime" in res1[0])
+        self.assertTrue(int(res1[0]["pwdLastSet"][0]) == 0)
+        delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
+
         try:
             ldb.add({
                 "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
@@ -1587,6 +1603,30 @@ class SamTests(samba.tests.TestCase):
         self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_NORMAL_ACCOUNT != 0)
         self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE != 0)
 
+        m = Message()
+        m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
+        m["lockoutTime"] = MessageElement(str(samba.unix2nttime(0)), FLAG_MOD_REPLACE, "lockoutTime")
+        m["pwdLastSet"] = MessageElement(str(samba.unix2nttime(0)), FLAG_MOD_REPLACE, "pwdLastSet")
+        ldb.modify(m)
+
+        m = Message()
+        m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
+        m["userAccountControl"] = MessageElement(
+          str(UF_LOCKOUT | UF_PASSWORD_EXPIRED),
+          FLAG_MOD_REPLACE, "userAccountControl")
+        ldb.modify(m)
+
+        res1 = ldb.search("cn=ldaptestuser,cn=users," + self.base_dn,
+                          scope=SCOPE_BASE,
+                          attrs=["sAMAccountType", "userAccountControl", "lockoutTime", "pwdLastSet"])
+        self.assertTrue(len(res1) == 1)
+        self.assertEquals(int(res1[0]["sAMAccountType"][0]),
+          ATYPE_NORMAL_ACCOUNT)
+        self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_NORMAL_ACCOUNT != 0)
+        self.assertTrue(int(res1[0]["userAccountControl"][0]) & (UF_LOCKOUT | UF_PASSWORD_EXPIRED) == 0)
+        self.assertTrue(int(res1[0]["lockoutTime"][0]) == 0)
+        self.assertTrue(int(res1[0]["pwdLastSet"][0]) == 0)
+
         try:
             m = Message()
             m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
@@ -1707,6 +1747,22 @@ class SamTests(samba.tests.TestCase):
         self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE == 0)
         delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
 
+        ldb.add({
+            "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
+            "objectclass": "computer",
+            "userAccountControl": str(UF_NORMAL_ACCOUNT | UF_PASSWD_NOTREQD | UF_LOCKOUT | UF_PASSWORD_EXPIRED)})
+
+        res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
+                          scope=SCOPE_BASE,
+                          attrs=["sAMAccountType", "userAccountControl", "lockoutTime", "pwdLastSet"])
+        self.assertTrue(len(res1) == 1)
+        self.assertEquals(int(res1[0]["sAMAccountType"][0]),
+          ATYPE_NORMAL_ACCOUNT)
+        self.assertTrue(int(res1[0]["userAccountControl"][0]) & (UF_LOCKOUT | UF_PASSWORD_EXPIRED) == 0)
+        self.assertFalse("lockoutTime" in res1[0])
+        self.assertTrue(int(res1[0]["pwdLastSet"][0]) == 0)
+        delete_force(self.ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
+
         try:
             ldb.add({
                 "dn": "cn=ldaptestcomputer,cn=computers," + self.base_dn,
@@ -1823,6 +1879,30 @@ class SamTests(samba.tests.TestCase):
         self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_NORMAL_ACCOUNT != 0)
         self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_ACCOUNTDISABLE != 0)
 
+        m = Message()
+        m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
+        m["lockoutTime"] = MessageElement(str(samba.unix2nttime(0)), FLAG_MOD_REPLACE, "lockoutTime")
+        m["pwdLastSet"] = MessageElement(str(samba.unix2nttime(0)), FLAG_MOD_REPLACE, "pwdLastSet")
+        ldb.modify(m)
+
+        m = Message()
+        m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
+        m["userAccountControl"] = MessageElement(
+          str(UF_LOCKOUT | UF_PASSWORD_EXPIRED),
+          FLAG_MOD_REPLACE, "userAccountControl")
+        ldb.modify(m)
+
+        res1 = ldb.search("cn=ldaptestcomputer,cn=computers," + self.base_dn,
+                          scope=SCOPE_BASE,
+                          attrs=["sAMAccountType", "userAccountControl", "lockoutTime", "pwdLastSet"])
+        self.assertTrue(len(res1) == 1)
+        self.assertEquals(int(res1[0]["sAMAccountType"][0]),
+          ATYPE_NORMAL_ACCOUNT)
+        self.assertTrue(int(res1[0]["userAccountControl"][0]) & UF_NORMAL_ACCOUNT != 0)
+        self.assertTrue(int(res1[0]["userAccountControl"][0]) & (UF_LOCKOUT | UF_PASSWORD_EXPIRED) == 0)
+        self.assertTrue(int(res1[0]["lockoutTime"][0]) == 0)
+        self.assertTrue(int(res1[0]["pwdLastSet"][0]) == 0)
+
         try:
             m = Message()
             m.dn = Dn(ldb, "cn=ldaptestcomputer,cn=computers," + self.base_dn)
diff --git a/source4/rpc_server/samr/dcesrv_samr.c b/source4/rpc_server/samr/dcesrv_samr.c
index 3826075..7279fe0 100644
--- a/source4/rpc_server/samr/dcesrv_samr.c
+++ b/source4/rpc_server/samr/dcesrv_samr.c
@@ -3510,8 +3510,14 @@ static NTSTATUS dcesrv_samr_SetUserInfo(struct dcesrv_call_state *dce_call, TALL
 		}
 
 		if (r->in.info->info26.password_expired > 0) {
+			NTTIME t = 0;
 			struct ldb_message_element *set_el;
-			if (samdb_msg_add_uint64(sam_ctx, mem_ctx, msg, "pwdLastSet", 0) != LDB_SUCCESS) {
+			if (r->in.info->info26.password_expired
+					== PASS_DONT_CHANGE_AT_NEXT_LOGON) {
+				unix_to_nt_time(&t, time(NULL));
+			}
+			if (samdb_msg_add_uint64(sam_ctx, mem_ctx, msg,
+						 "pwdLastSet", t) != LDB_SUCCESS) {
 				return NT_STATUS_NO_MEMORY;
 			}
 			set_el = ldb_msg_find_element(msg, "pwdLastSet");


-- 
Samba Shared Repository


More information about the samba-cvs mailing list