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 <[email protected]>
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 <[email protected]>
    
    Autobuild-User(master): Andrew Bartlett <[email protected]>
    Autobuild-Date(master): Mon Jun 10 07:32:35 CEST 2013 on sn-devel-104

commit 2f7d9fddf7102d76b182fbd50ccaf18cb5a10014
Author: Matthias Dieter Wallnöfer <[email protected]>
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 <[email protected]>

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

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

Reply via email to