Patch implementing bad password lockout on LDAP backend, samba-3.0.2rc1

Jianliang Lu j.lu at tiesse.com
Tue Jan 27 15:25:09 GMT 2004


In attachment is my patch.

I've added two attributes to SamAccount in samba.schema: one 
is "badPasswordCount" and another is "badPasswordTime".

During the logon process, the autolock flag is updated if the "duration" time 
is reached. Also the bad_password_count is reset when the "reset count time" 
is reached and if it's not zero. When the passord check results wrong 
password then the bad_password_count is increased to one and the account will 
be lockout if the "bad lockout attempt" is reached.

The autolock flag is also checked and updated when a SAMR_QUERY_USERINFO is 
called and the level of query is 10, 12, 20 or 21, while the 
bad_password_count/bad_password_time is updated only for the query level 21.

Autolock and bad_password_count are updated also when you would show the user 
using pdbedit -u user -v. You can reset the bad_password_count using pdbedit -
u user -z.

TODO: when user try to change the password without logon we should also catch 
it and apply the password policy.

Any comment is precious for me.

Jianliang Lu

--------------------------- Ptach ----------------------------------


--- ./examples/LDAP/samba.schema.orig	Wed Jan 21 14:34:59 2004
+++ ./examples/LDAP/samba.schema	Fri Jan 23 09:05:44 2004
@@ -202,6 +202,15 @@
 	EQUALITY integerMatch
 	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
 
+attributetype ( 1.3.6.1.4.1.7165.2.1.50 NAME 'badPasswordCount'
+	DESC 'NT bad password attempt count'
+	EQUALITY integerMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.7165.2.1.51 NAME 'badPasswordTime'
+	DESC 'Timestamp of the last bad password attempt update'
+	EQUALITY integerMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
 
 ##
 ## string settings
@@ -313,7 +322,8 @@
 	       sambaPwdCanChange $ sambaPwdMustChange $ sambaAcctFlags $
                displayName $ sambaHomePath $ sambaHomeDrive $ 
sambaLogonScript $
 	       sambaProfilePath $ description $ sambaUserWorkstations $
-	       sambaPrimaryGroupSID $ sambaDomainName $ sambaMungedDial))
+	       sambaPrimaryGroupSID $ sambaDomainName $ sambaMungedDial $
+		   badPasswordCount $ badPasswordTime))
 
 ##
 ## Group mapping info
--- ./source/auth/auth_sam.c.orig	Thu Jan 22 14:41:43 2004
+++ ./source/auth/auth_sam.c	Tue Jan 27 10:15:52 2004
@@ -74,10 +74,12 @@
 			       SAM_ACCOUNT *sampass, 
 			       const auth_usersupplied_info *user_info)
 {
-	uint16	acct_ctrl = pdb_get_acct_ctrl(sampass);
+	uint16	acct_ctrl;
 	char *workstation_list;
 	time_t kickoff_time;
 	
+	acct_ctrl = pdb_get_acct_ctrl(sampass);
+
 	DEBUG(4,("sam_account_ok: Checking SMB password for user %
s\n",pdb_get_username(sampass)));
 
 	/* Quit if the account was disabled. */
@@ -86,12 +88,6 @@
 		return NT_STATUS_ACCOUNT_DISABLED;
 	}
 
-	/* Quit if the account was locked out. */
-	if (acct_ctrl & ACB_AUTOLOCK) {
-		DEBUG(1,("sam_account_ok: Account for user %s was locked 
out.\n", pdb_get_username(sampass)));
-		return NT_STATUS_ACCOUNT_LOCKED_OUT;
-	}
-
 	/* Test account expire time */
 	
 	kickoff_time = pdb_get_kickoff_time(sampass);
@@ -177,8 +173,11 @@
 	SAM_ACCOUNT *sampass=NULL;
 	BOOL ret;
 	NTSTATUS nt_status;
+	GROUP_MAP map;
+	pstring grname;
 	DATA_BLOB user_sess_key = data_blob(NULL, 0);
 	DATA_BLOB lm_sess_key = data_blob(NULL, 0);
+	BOOL updated=False, updated1=False;
 
 	if (!user_info || !auth_context) {
 		return NT_STATUS_UNSUCCESSFUL;
@@ -202,14 +201,58 @@
 		return NT_STATUS_NO_SUCH_USER;
 	}
 
+	if (pdb_get_acct_ctrl(sampass) & ACB_NORMAL)
+		pdb_update_autolock_flag(sampass, &updated);
+
+	/* Quit if the account was locked out. */
+	if (pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK) {
+		DEBUG(3,("check_sam_security: Account for user %s was locked 
out.\n", pdb_get_username(sampass)));
+		return NT_STATUS_ACCOUNT_LOCKED_OUT;
+	}
+
+
 	nt_status = sam_password_ok(auth_context, mem_ctx, sampass, 
 				    user_info, &user_sess_key, &lm_sess_key);
 	
 	if (!NT_STATUS_IS_OK(nt_status)) {
+		if (NT_STATUS_EQUAL(nt_status,NT_STATUS_WRONG_PASSWORD) && 
pdb_get_acct_ctrl(sampass) &ACB_NORMAL) {  
+
+			if (!pdb_getgrnam(&map, "Domain Admins"))
+                DEBUG(1, ("auth_sam.c: Failed to get groupmap for Domain 
Admins"));
+			else
+	            pstrcpy(grname, gidtoname(map.gid));
+			if(!user_in_group_list(user_info-
>internal_username.str,grname,NULL,0)){
+				pdb_increment_bad_password_count(sampass);
+				updated1 = True;
+			}
+		} else {
+				if (!pdb_update_bad_password_count(sampass, 
&updated1))
+					DEBUG(2,
("pdb_update_bad_password_count failed.\n"));
+		}
+		if (updated || updated1){
+			become_root();
+			if(!pdb_update_sam_account(sampass))
+				DEBUG(1, ("Failed to modify entry.\n"));
+			unbecome_root();
+		}
 		pdb_free_sam(&sampass);
 		return nt_status;
 	}
 
+	if ((pdb_get_acct_ctrl(sampass) & ACB_NORMAL) && 
+								
	(pdb_get_bad_password_count(sampass) > 0)){
+		pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
+		pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
+		updated1 = True;
+	}
+
+	if (updated || updated1){
+		become_root();
+		if(!pdb_update_sam_account(sampass))
+			DEBUG(1, ("Failed to modify entry.\n"));
+		unbecome_root();
+	}
+
 	nt_status = sam_account_ok(mem_ctx, sampass, user_info);
 
 	if (!NT_STATUS_IS_OK(nt_status)) {
--- ./source/include/smbldap.h.orig	Wed Jan 21 15:10:39 2004
+++ ./source/include/smbldap.h	Wed Jan 21 15:37:15 2004
@@ -91,6 +91,7 @@
 #define LDAP_ATTR_BAD_PASSWORD_COUNT	35
 #define LDAP_ATTR_LOGON_COUNT		36
 #define LDAP_ATTR_MUNGED_DIAL		37
+#define LDAP_ATTR_BAD_PASSWORD_TIME		38
 
 typedef struct _attrib_map_entry {
 	int		attrib;
--- ./source/include/passdb.h.orig	Thu Jan 22 10:55:51 2004
+++ ./source/include/passdb.h	Thu Jan 22 11:39:40 2004
@@ -50,6 +50,7 @@
 	PDB_GROUPSID,
 	PDB_ACCTCTRL,
 	PDB_PASSLASTSET,
+	PDB_BAD_PASSWORD_TIME,	
 	PDB_UNIXHOMEDIR,
 	PDB_ACCTDESC,
 	PDB_WORKSTATIONS,
@@ -108,6 +109,7 @@
 		time_t pass_last_set_time;    /* password last set time */
 		time_t pass_can_change_time;  /* password can change time */
 		time_t pass_must_change_time; /* password must change time */
+		time_t bad_password_time; 	  /* last bad password 
attempt time */
 		
 		const char * username;     /* UNIX username string */
 		const char * domain;       /* Windows Domain name */

--- ./source/lib/smbldap.c.orig	Wed Jan 21 15:09:11 2004
+++ ./source/lib/smbldap.c	Fri Jan 23 09:08:57 2004
@@ -98,6 +98,8 @@
 	{ LDAP_ATTR_OBJCLASS,		"objectClass"		},
 	{ LDAP_ATTR_ACB_INFO,		"sambaAcctFlags"	},
 	{ LDAP_ATTR_MUNGED_DIAL,	"sambaMungedDial"	},
+	{ LDAP_ATTR_BAD_PASSWORD_COUNT,	"badPasswordCount"	},
+	{ LDAP_ATTR_BAD_PASSWORD_TIME,	"badPasswordTime"	},
 	{ LDAP_ATTR_LIST_END,		NULL 			}
 };

--- ./source/passdb/pdb_ldap.c.orig	Wed Jan 21 15:08:02 2004
+++ ./source/passdb/pdb_ldap.c	Thu Jan 22 11:40:44 2004
@@ -405,7 +405,8 @@
 			kickoff_time,
 			pass_last_set_time, 
 			pass_can_change_time, 
-			pass_must_change_time;
+			pass_must_change_time,
+			bad_password_time;
 	pstring 	username, 
 			domain,
 			nt_username,
@@ -722,6 +723,14 @@
 		pdb_set_bad_password_count(sampass, bad_password_count, 
PDB_SET);
 	}
 
+	if (!smbldap_get_single_attribute(ldap_state->smbldap_state-
>ldap_struct, entry, 
+			get_userattr_key2string(ldap_state->schema_ver, 
LDAP_ATTR_BAD_PASSWORD_TIME), temp)) {
+		/* leave as default */
+	} else {
+		bad_password_time = (time_t) atol(temp);
+		pdb_set_bad_password_time(sampass, bad_password_time, 
PDB_SET);
+	}
+
 	if (!smbldap_get_single_attribute(ldap_state->smbldap_state-
>ldap_struct, entry,
 			get_userattr_key2string(ldap_state->schema_ver, 
LDAP_ATTR_LOGON_COUNT), temp)) {
 			/* leave as default */
@@ -909,6 +918,16 @@
 		smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, 
existing, mods,
 			get_userattr_key2string(ldap_state->schema_ver, 
LDAP_ATTR_PWD_MUST_CHANGE), temp);
 
+	slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_bad_password_time
(sampass));
+	if (need_update(sampass, PDB_BAD_PASSWORD_TIME))
+		smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, 
existing, mods,
+			get_userattr_key2string(ldap_state->schema_ver, 
LDAP_ATTR_BAD_PASSWORD_TIME), temp);
+
+	slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_bad_password_count
(sampass));
+	if (need_update(sampass, PDB_BAD_PASSWORD_COUNT))
+		smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, 
existing, mods,
+			get_userattr_key2string(ldap_state->schema_ver, 
LDAP_ATTR_BAD_PASSWORD_COUNT), temp);
+
 	if ((pdb_get_acct_ctrl(sampass)&
(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST))
 			|| (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_ONLY)) {
 
--- ./source/passdb/passdb.c.orig	Thu Jan 22 10:58:01 2004
+++ ./source/passdb/passdb.c	Tue Jan 27 15:08:24 2004
@@ -79,6 +79,7 @@
 	user->private.logoff_time           = 
 	user->private.kickoff_time          = 
 	user->private.pass_must_change_time = get_time_t_max();
+	user->private.bad_password_time     = (time_t)0;
 	user->private.unknown_3 = 0x00ffffff; 	/* don't know */
 	user->private.logon_divs = 168; 	/* hours per week */
 	user->private.hours_len = 21; 		/* 21 times 8 bits = 168 */
@@ -1765,3 +1766,107 @@
 }
 
 
+/*********************************************************************
+ Update the bad password count checking the AP_RESET_COUNT_TIME 
+ ********************************************************************/
+
+BOOL pdb_update_bad_password_count(SAM_ACCOUNT *sampass, BOOL *updated)
+{
+	time_t LastBadPassword;
+	uint16 BadPasswordCount;
+	uint32 resettime; 
+
+	BadPasswordCount = pdb_get_bad_password_count(sampass);
+	if(BadPasswordCount > 0){
+		if (!account_policy_get(AP_RESET_COUNT_TIME, &resettime)) {
+				DEBUG(0, ("account_policy_get failed.\n"));
+				return False;
+		} else {
+				LastBadPassword = pdb_get_bad_password_time
(sampass);	
+				DEBUG(10, ("LastBadPassword=%d, resettime=%
d.\n", LastBadPassword, resettime));
+				if ((resettime < 0xffffffff) && (time(NULL) > 
(LastBadPassword + resettime*60))){
+					pdb_set_bad_password_count(sampass, 
0, PDB_CHANGED);
+					pdb_set_bad_password_time(sampass, 0, 
PDB_CHANGED);
+					*updated =True;
+				}		
+		}
+	}
+	return True;
+}
+
+/*********************************************************************
+ Update the ACB_AUTOLOCK flag checking the AP_LOCK_ACCOUNT_DURATION 
+ ********************************************************************/
+
+BOOL pdb_update_autolock_flag(SAM_ACCOUNT *sampass, BOOL *updated)
+{
+	uint32 duration;
+	time_t LastBadPassword;
+
+	if (!sampass)
+		return False;
+
+	if (pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK)
+		if (!account_policy_get(AP_LOCK_ACCOUNT_DURATION, &duration)) 
{
+				DEBUG(0, ("pdb_update_autolock_flag: 
account_policy_get failed.\n"));
+				return False;
+		} else {
+				LastBadPassword = pdb_get_bad_password_time
(sampass);	
+				DEBUG(10, ("LastBadPassword=%d, duration=%
d.\n",LastBadPassword,duration*60 ));
+				if ((duration < 0xffffffff) && (time(NULL) > 
(LastBadPassword + duration*60))){
+					DEBUG(10, ("LastBadPassword=%d, 
duration=%d.\n",LastBadPassword,duration*60 ));
+					pdb_set_acct_ctrl (sampass,
+							
	pdb_get_acct_ctrl(sampass) & ~ACB_AUTOLOCK,
+								PDB_CHANGED);
+					pdb_set_bad_password_count(sampass, 
0, PDB_CHANGED);
+					pdb_set_bad_password_time(sampass, 0, 
PDB_CHANGED);
+
+					*updated =True;
+				}		
+		}
+
+	return True;
+}
+
+/*********************************************************************
+ Increment the bad_password_count 
+ ********************************************************************/
+
+BOOL pdb_increment_bad_password_count(SAM_ACCOUNT *sampass)
+{
+	uint32 resettime;
+	uint32 account_policy_lockout;
+	time_t LastBadPassword;
+
+	if (!sampass)
+		return False;
+	
+	if (!account_policy_get(AP_RESET_COUNT_TIME, &resettime)) {
+			DEBUG(0, ("account_policy_get failed.\n"));
+			return False;
+	} else {
+			LastBadPassword = pdb_get_bad_password_time(sampass);
	
+			DEBUG(10, ("LastBadPassword=%d, resettime=%d.\n", 
LastBadPassword, resettime));
+			if (time(NULL) > (LastBadPassword + resettime*60)){
+				pdb_set_bad_password_count(sampass, 1, 
PDB_CHANGED);
+			}else		
+				pdb_set_bad_password_count(sampass, 
+									
	pdb_get_bad_password_count(sampass)+1,
+									
	PDB_CHANGED);
+			pdb_set_bad_password_time(sampass, time(NULL), 
PDB_CHANGED);
+			if (!account_policy_get
(AP_BAD_ATTEMPT_LOCKOUT,&account_policy_lockout)) {
+				DEBUG(0, ("account_policy_get failed.\n"));
+				return False;
+			} else {
+				if (account_policy_lockout && 
+					(pdb_get_bad_password_count(sampass) 
>= account_policy_lockout))
+					if (!pdb_set_acct_ctrl (sampass,
+								
	pdb_get_acct_ctrl(sampass) |ACB_AUTOLOCK,
+								
	PDB_CHANGED)) {
+						DEBUG(1, 
("pdb_increment_bad_password_count:failed to set 'autolock' flag. \n")); 
+						return False;
+					} 
+			}		
+			return True;
+	}
+}
--- ./source/passdb/pdb_get_set.c.orig	Thu Jan 22 11:05:47 2004
+++ ./source/passdb/pdb_get_set.c	Thu Jan 22 16:55:02 2004
@@ -96,6 +96,14 @@
 		return (-1);
 }
 
+time_t pdb_get_bad_password_time (const SAM_ACCOUNT *sampass)
+{
+	if (sampass)
+		return (sampass->private.bad_password_time);
+	else
+		return (-1);
+}
+
 uint16 pdb_get_logon_divs (const SAM_ACCOUNT *sampass)
 {
 	if (sampass)
@@ -420,6 +428,16 @@
 	return pdb_set_init_flags(sampass, PDB_PASSLASTSET, flag);
 }
 
+BOOL pdb_set_bad_password_time (SAM_ACCOUNT *sampass, time_t mytime, enum 
pdb_value_state flag)
+{
+	if (!sampass)
+		return False;
+
+	sampass->private.bad_password_time = mytime;
+
+	return pdb_set_init_flags(sampass, PDB_BAD_PASSWORD_TIME, flag);
+}
+
 BOOL pdb_set_hours_len (SAM_ACCOUNT *sampass, uint32 len, enum 
pdb_value_state flag)
 {
 	if (!sampass)
@@ -1128,3 +1146,4 @@
 
 	return True;
 }
+

--- ./source/rpc_server/srv_samr_nt.c.orig	Tue Jan 27 13:47:31 2004
+++ ./source/rpc_server/srv_samr_nt.c	Tue Jan 27 14:05:12 2004
@@ -1656,6 +1656,7 @@
 	SAM_ACCOUNT *smbpass=NULL;
 	BOOL ret;
 	NTSTATUS nt_status;
+	BOOL updated=False;
 
 	nt_status = pdb_init_sam_talloc(mem_ctx, &smbpass);
 	
@@ -1674,6 +1675,16 @@
 
 	DEBUG(3,("User:[%s]\n", pdb_get_username(smbpass) ));
 
+	pdb_update_autolock_flag(smbpass, &updated);
+	
+	if (updated){
+		become_root();
+		if(!pdb_update_sam_account(smbpass))
+			DEBUG(1, ("Failed to modify entry.\n"));
+		unbecome_root();
+	}
+
+
 	ZERO_STRUCTP(id10);
 	init_sam_user_info10(id10, pdb_get_acct_ctrl(smbpass) );
 
@@ -1693,6 +1704,7 @@
 	SAM_ACCOUNT *smbpass=NULL;
 	BOOL ret;
 	NTSTATUS nt_status;
+	BOOL updated=False;
 
 	if (!p->ntlmssp_auth_validated)
 		return NT_STATUS_ACCESS_DENIED;
@@ -1720,6 +1732,15 @@
 
 	DEBUG(3,("User:[%s] 0x%x\n", pdb_get_username(smbpass), 
pdb_get_acct_ctrl(smbpass) ));
 
+	pdb_update_autolock_flag(smbpass, &updated);
+	
+	if (updated){
+		become_root();
+		if(!pdb_update_sam_account(smbpass))
+			DEBUG(1, ("Failed to modify entry.\n"));
+		unbecome_root();
+	}
+
 	if ( pdb_get_acct_ctrl(smbpass) & ACB_DISABLED) {
 		pdb_free_sam(&smbpass);
 		return NT_STATUS_ACCOUNT_DISABLED;
@@ -1741,6 +1762,7 @@
 {
 	SAM_ACCOUNT *sampass=NULL;
 	BOOL ret;
+	BOOL updated=False;
 
 	pdb_init_sam_talloc(mem_ctx, &sampass);
 
@@ -1757,6 +1779,15 @@
 
 	DEBUG(3,("User:[%s]\n",  pdb_get_username(sampass) ));
 
+	pdb_update_autolock_flag(sampass, &updated);
+	
+	if (updated){
+		become_root();
+		if(!pdb_update_sam_account(sampass))
+			DEBUG(1, ("Failed to modify entry.\n"));
+		unbecome_root();
+	}
+
 	ZERO_STRUCTP(id20);
 	init_sam_user_info20A(id20, sampass);
 	
@@ -1775,6 +1806,7 @@
 	SAM_ACCOUNT *sampass=NULL;
 	BOOL ret;
 	NTSTATUS nt_status;
+	BOOL updated=False, updated1=False;
 
 	nt_status = pdb_init_sam_talloc(mem_ctx, &sampass);
 	if (!NT_STATUS_IS_OK(nt_status)) {
@@ -1794,6 +1826,16 @@
 
 	DEBUG(3,("User:[%s]\n",  pdb_get_username(sampass) ));
 
+	pdb_update_autolock_flag(sampass, &updated);
+	pdb_update_bad_password_count(sampass, &updated1);
+	
+	if (updated || updated1){
+		become_root();
+		if(!pdb_update_sam_account(sampass))
+			DEBUG(1, ("Failed to modify entry.\n"));
+		unbecome_root();
+	}
+
 	ZERO_STRUCTP(id21);
 	nt_status = init_sam_user_info21A(id21, sampass, domain_sid);
 	
--- ./source/utils/pdbedit.c.orig	Mon Jan 26 18:01:10 2004
+++ ./source/utils/pdbedit.c	Tue Jan 27 11:44:27 2004
@@ -47,6 +47,7 @@
 #define BIT_RESERV_7	0x00800000
 #define BIT_IMPORT	0x01000000
 #define BIT_EXPORT	0x02000000
+#define BIT_BADPWRESET  0x04000000 
 
 #define MASK_ALWAYS_GOOD	0x0000001F
 #define MASK_USER_GOOD		0x00401F00
@@ -153,6 +154,10 @@
 		tmp = pdb_get_pass_must_change_time(sam_pwent);
 		printf ("Password must change: %s\n", tmp ? http_timestring
(tmp) : "0");
 		
+		tmp = pdb_get_bad_password_time(sam_pwent);
+		printf ("Last Bad Password Time: %s\n", tmp ? http_timestring
(tmp) : "0");
+		printf ("Bad Password Count: %d\n", pdb_get_bad_password_count
(sam_pwent));
+		
 	} else if (smbpwdstyle) {
 		char lm_passwd[33];
 		char nt_passwd[33];
@@ -185,6 +190,8 @@
 {
 	SAM_ACCOUNT *sam_pwent=NULL;
 	BOOL ret;
+	BOOL updated = False, updated1=False;
+
 	
 	if (!NT_STATUS_IS_OK(pdb_init_sam (&sam_pwent))) {
 		return -1;
@@ -197,6 +204,19 @@
 		pdb_free_sam(&sam_pwent);
 		return -1;
 	}
+
+	if (!pdb_update_autolock_flag(sam_pwent, &updated))
+	        DEBUG(2,("pdb_update_autolock_flag failed.\n"));
+
+	if (!pdb_update_bad_password_count(sam_pwent, &updated))
+	        DEBUG(2,("pdb_update_bad_password_count failed.\n"));
+	
+	if (updated || updated1){
+		become_root();
+		if(!pdb_update_sam_account(sam_pwent))
+			DEBUG(1, ("Failed to modify entry.\n"));
+		unbecome_root();
+	}
 	
 	ret=print_sam_info (sam_pwent, verbosity, smbpwdstyle);
 	pdb_free_sam(&sam_pwent);
@@ -241,7 +261,7 @@
 			  const char *fullname, const char *homedir, 
 			  const char *drive, const char *script, 
 			  const char *profile, const char *account_control,
-			  const char *user_sid, const char *group_sid)
+			  const char *user_sid, const char *group_sid,const 
BOOL badpw)
 {
 	SAM_ACCOUNT *sam_pwent=NULL;
 	BOOL ret;
@@ -313,6 +333,11 @@
 		pdb_set_group_sid (sam_pwent, &g_sid, PDB_CHANGED);
 	}
 	
+	if (badpw){
+	        pdb_set_bad_password_count(sam_pwent, 0, PDB_CHANGED);
+	        pdb_set_bad_password_time(sam_pwent, 0, PDB_CHANGED);
+	}
+
 	if (NT_STATUS_IS_OK(in->pdb_update_sam_account (in, sam_pwent)))
 		print_user_info (in, username, True, False);
 	else {
@@ -558,6 +583,7 @@
 	static char *group_sid = NULL;
 	static long int account_policy_value = 0;
 	BOOL account_policy_value_set = False;
+	static BOOL badpw_reset = False;  
 
 	struct pdb_context *bin;
 	struct pdb_context *bout;
@@ -587,6 +613,7 @@
 		{"account-policy",	'P', POPT_ARG_STRING, 
&account_policy, 0,"value of an account policy (like maximum password 
age)",NULL},
 		{"value",       'C', POPT_ARG_LONG, 
&account_policy_value, 'C',"set the account policy to this value", NULL},
 		{"account-control",	'c', POPT_ARG_STRING, 
&account_control, 0, "Values of account control", NULL},
+		{"bad-password-count-reset", 'z', POPT_ARG_NONE, 
&badpw_reset, 0, "reset bad password count" , NULL},
 		POPT_COMMON_SAMBA
 		POPT_TABLEEND
 	};
@@ -638,7 +665,8 @@
 			(account_policy ? BIT_ACCPOLICY : 0) +
 			(account_policy_value_set ? BIT_ACCPOLVAL : 0) +
 			(backend_in ? BIT_IMPORT : 0) +
-			(backend_out ? BIT_EXPORT : 0);
+			(backend_out ? BIT_EXPORT : 0) +
+			(badpw_reset ? BIT_BADPWRESET : 0);
 
 	if (setparms & BIT_BACKEND) {
 		if (!NT_STATUS_IS_OK(make_pdb_context_string(&bdef, 
backend))) {
@@ -732,6 +760,11 @@
 	/* mask out users options */
 	checkparms &= ~MASK_USER_GOOD;
 	
+	if (checkparms & BIT_BADPWRESET){
+		checkparms |= BIT_MODIFY; 
+		checkparms &= ~BIT_BADPWRESET; 
+	}
+
 	/* account operation */
 	if ((checkparms & BIT_CREATE) || (checkparms & BIT_MODIFY) || 
(checkparms & BIT_DELETE)) {
 		/* check use of -u option */
@@ -767,7 +800,7 @@
 					      home_drive,
 					      logon_script,
 					      profile_path, account_control,
-					      user_sid, group_sid);
+					      user_sid, 
group_sid,badpw_reset);
 		}
 	}

Jianliang Lu
TieSse s.p.a.     Ivrea (To) - Italy
j.lu at tiesse.com   luj at libero.it
http://www.tiesse.com


More information about the samba-technical mailing list