[PATCH] bad password lock

Aurélien Degrémont adegremont at idealx.com
Tue Sep 16 12:33:45 GMT 2003


Hi,

Here is the new version of the Richard Renard's patch, which enables the 
bad password count and lockout duration functionnalities.

I note that Jeremy Allison was already working on it, and that some 
people were waiting for it :). I hope this patch will be useful.

This patch is based on Jianliang Lu patch 
(http://lists.samba.org/pipermail/samba-technical/2003-May/044645.html) 
but was mainly rewritten.

This new version enables theses new functionnalities on all the 
available backends of Samba (tdbsam, xml, mysql, ldap).

This patch adds 2 fields in the ldap schema
  - sambaBadPwdCount
  - sambaLockoutDuration
And in the MySQL table :
  - bad_pwd_count
  - lockout_time

Obviously, due to smbpasswd limitations, these features are not 
available on it.

An option ( -z ) to reset the bad password count was added in pdbedit.

This patch needs tests and i'm waiting for your comments.


Best regards,

Aurélien Degrémont
-------------- next part --------------
Index: examples/LDAP/samba.schema
===================================================================
RCS file: /opt/cvs/prj/infra/serveur_proximite/samba/source/examples/LDAP/samba.schema,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.2.1
diff -u -r1.1.1.1 -r1.1.1.1.2.1
--- examples/LDAP/samba.schema	11 Sep 2003 15:45:29 -0000	1.1.1.1
+++ examples/LDAP/samba.schema	11 Sep 2003 15:58:25 -0000	1.1.1.1.2.1
@@ -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 'sambaBadPwdCount'
+	DESC 'Bad Password Attempt'
+	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 'sambaLockoutTime'
+	DESC 'Timestamp of when the user was locked out'
+	EQUALITY integerMatch
+	SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
 
 ##
 ## string settings
@@ -304,8 +313,8 @@
 	DESC 'Samba 3.0 Auxilary SAM Account'
 	MUST ( uid $ sambaSID )
 	MAY  ( cn $ sambaLMPassword $ sambaNTPassword $ sambaPwdLastSet $
-	       sambaLogonTime $ sambaLogoffTime $ sambaKickoffTime $
-	       sambaPwdCanChange $ sambaPwdMustChange $ sambaAcctFlags $
+	       sambaLogonTime $ sambaLogoffTime $ sambaKickoffTime $ sambaLockoutTime $ 
+	       sambaBadPwdCount $ sambaPwdCanChange $ sambaPwdMustChange $ sambaAcctFlags $
                displayName $ sambaHomePath $ sambaHomeDrive $ sambaLogonScript $
 	       sambaProfilePath $ description $ sambaUserWorkstations $
 	       sambaPrimaryGroupSID $ sambaDomainName ))
Index: source/auth/auth_sam.c
===================================================================
RCS file: /opt/cvs/prj/infra/serveur_proximite/samba/source/source/auth/auth_sam.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.2.1
diff -u -r1.1.1.1 -r1.1.1.1.2.1
--- source/auth/auth_sam.c	11 Sep 2003 15:45:30 -0000	1.1.1.1
+++ source/auth/auth_sam.c	11 Sep 2003 15:58:26 -0000	1.1.1.1.2.1
@@ -156,8 +156,15 @@
 	uint16 acct_ctrl;
 	const uint8 *nt_pw, *lm_pw;
 	uint32 auth_flags;
-
+	
 	acct_ctrl = pdb_get_acct_ctrl(sampass);
+
+	/* Quit if the account was locked out. */
+	if (acct_ctrl & ACB_AUTOLOCK) {
+		DEBUG(1,("Account for user %s was locked out.\n", pdb_get_username(sampass)));
+		return NT_STATUS_ACCOUNT_LOCKED_OUT;
+	}
+
 	if (acct_ctrl & ACB_PWNOTREQ) 
 	{
 		if (lp_null_passwords()) 
@@ -404,6 +411,8 @@
 check if a username/password is OK assuming the password is a 24 byte
 SMB hash supplied in the user_info structure
 return an NT_STATUS constant.
+
+hacked by Richard Renard for IDEALX
 ****************************************************************************/
 
 static NTSTATUS check_sam_security(const struct auth_context *auth_context,
@@ -417,6 +426,9 @@
 	NTSTATUS nt_status;
 	uint8 user_sess_key[16];
 	const uint8* lm_hash;
+	uint32 account_policy_lockout, badpwdcount,
+		account_policy_lockout_duration;
+	time_t lockout_time;
 
 	if (!user_info || !auth_context) {
 		return NT_STATUS_UNSUCCESSFUL;
@@ -443,9 +455,61 @@
 
 	nt_status = sam_password_ok(auth_context, mem_ctx, sampass, user_info, user_sess_key);
 	
+	/* if WRONG_PASSWORD set badpwdcount and lock the account if needed */
 	if (!NT_STATUS_IS_OK(nt_status)) {
+		if (NT_STATUS_EQUAL(nt_status,NT_STATUS_WRONG_PASSWORD) && pdb_get_acct_ctrl(sampass) &ACB_NORMAL) {
+			badpwdcount = (uint32)pdb_get_bad_pwd_count(sampass) + 1 ;
+			if (!pdb_set_bad_pwd_count(sampass, badpwdcount, PDB_CHANGED))
+				DEBUG(1,("Failed to set 'badPwdCount' for user %s. \n", user_info->internal_username.str));
+			account_policy_get(AP_BAD_ATTEMPT_LOCKOUT, &account_policy_lockout);
+			if (account_policy_lockout && (badpwdcount > account_policy_lockout)) {
+				nt_status = NT_STATUS_ACCOUNT_LOCKED_OUT;
+				lockout_time = time(NULL);
+				if(!pdb_set_acct_ctrl (sampass, pdb_get_acct_ctrl(sampass)|ACB_AUTOLOCK, PDB_CHANGED))
+					DEBUG(1, ("Failed to set 'lockout' flag for user %s. \n", user_info->internal_username.str));
+				if(!pdb_set_lockout_time(sampass, lockout_time, PDB_CHANGED))
+					DEBUG(1, ("Failed to set 'lockout_time' for user %s \n", user_info->internal_username.str));
+			}
+			
+			become_root();
+			if (!pdb_update_sam_account(sampass)) 
+				DEBUG(1, ("Failed to modify entry for user %s. \n", user_info->internal_username.str));
+			unbecome_root();
+			
+		}
 		pdb_free_sam(&sampass);
 		return nt_status;
+	}
+	
+	/* if the account is locked, unlock it if lockout duration is expired */
+	if (pdb_get_acct_ctrl(sampass) &ACB_AUTOLOCK) {
+		lockout_time = (time_t)pdb_get_lockout_time(sampass);
+		account_policy_get(AP_LOCK_ACCOUNT_DURATION, &account_policy_lockout_duration);
+		if ( ((time_t)lockout_time + (time_t)account_policy_lockout_duration) < time(NULL) &&
+				((time_t)lockout_time + (time_t)account_policy_lockout_duration) > (time_t)lockout_time) {
+			if(!pdb_set_acct_ctrl (sampass, pdb_get_acct_ctrl(sampass) ^ACB_AUTOLOCK, PDB_CHANGED))
+				DEBUG(1, ("Failed to remove 'lockout' flag for user %s. \n", user_info->internal_username.str));
+			if(!pdb_set_lockout_time(sampass, (time_t)0, PDB_CHANGED))
+				DEBUG(1, ("Failed to remove 'lockout_time' for user %s \n", user_info->internal_username.str));
+
+			become_root();
+			if (!pdb_update_sam_account(sampass))
+				DEBUG(1, ("Failed to modify entry for user %s. \n", user_info->internal_username.str));
+			unbecome_root();
+		}
+	}
+
+	/* reset badpwdcount if account is normal*/
+	if (pdb_get_acct_ctrl(sampass) &ACB_NORMAL) {
+		if (!pdb_set_bad_pwd_count(sampass, 0, PDB_CHANGED))
+			DEBUG(1, ("Failed to reset 'BadPwdCount' for user %s. \n", user_info->internal_username.str));
+		if (!pdb_set_logon_time(sampass, time(NULL), PDB_CHANGED))
+			DEBUG(1, ("auth_sam.c : pdb_set_logon_time failed! \n"));
+		
+		become_root();
+		if (!pdb_update_sam_account(sampass))
+			DEBUG(1, ("Failed to modify entry for user %s. \n", user_info->internal_username.str));
+		unbecome_root();
 	}
 
 	nt_status = sam_account_ok(mem_ctx, sampass, user_info);
Index: source/include/passdb.h
===================================================================
RCS file: /opt/cvs/prj/infra/serveur_proximite/samba/source/source/include/passdb.h,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.2.1
diff -u -r1.1.1.1 -r1.1.1.1.2.1
--- source/include/passdb.h	11 Sep 2003 15:45:31 -0000	1.1.1.1
+++ source/include/passdb.h	11 Sep 2003 15:58:27 -0000	1.1.1.1.2.1
@@ -62,6 +62,8 @@
 	PDB_LMPASSWD,
 	PDB_NTPASSWD,
 	PDB_BACKEND_PRIVATE_DATA,
+	PDB_BADPWDCOUNT,
+	PDB_LOCKOUTTIME,
 
 	/* this must be the last element */
 	PDB_COUNT
@@ -104,6 +106,7 @@
 		time_t logon_time;            /* logon time */
 		time_t logoff_time;           /* logoff time */
 		time_t kickoff_time;          /* kickoff time */
+		time_t lockout_time;          /* lockout time */
 		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 */
@@ -138,6 +141,7 @@
 		
 		uint32 unknown_5; /* 0x0002 0000 */
 		uint32 unknown_6; /* 0x0000 04ec */
+		uint32 bad_pwd_count; /* count of bad password attempts */
 		/* a tag for who added the private methods */
 		const struct pdb_methods *backend_private_methods;
 		void *backend_private_data; 
Index: source/include/smbldap.h
===================================================================
RCS file: /opt/cvs/prj/infra/serveur_proximite/samba/source/source/include/smbldap.h,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.2.1
diff -u -r1.1.1.1 -r1.1.1.1.2.1
--- source/include/smbldap.h	11 Sep 2003 15:45:31 -0000	1.1.1.1
+++ source/include/smbldap.h	11 Sep 2003 15:58:27 -0000	1.1.1.1.2.1
@@ -88,6 +88,8 @@
 #define LDAP_ATTR_SID			32
 #define LDAP_ATTR_ALGORITHMIC_RID_BASE  33
 #define LDAP_ATTR_NEXT_RID              34
+#define LDAP_ATTR_BAD_PWD_COUNT         35
+#define LDAP_ATTR_LOCKOUT_TIME          36
 
 typedef struct _attrib_map_entry {
 	int		attrib;
Index: source/lib/smbldap.c
===================================================================
RCS file: /opt/cvs/prj/infra/serveur_proximite/samba/source/source/lib/smbldap.c,v
retrieving revision 1.1.1.1.4.1
retrieving revision 1.1.1.1.2.2
diff -u -r1.1.1.1.4.1 -r1.1.1.1.2.2
--- source/lib/smbldap.c	15 Sep 2003 09:59:15 -0000	1.1.1.1.4.1
+++ source/lib/smbldap.c	15 Sep 2003 14:24:03 -0000	1.1.1.1.2.2
@@ -97,6 +97,8 @@
 	{ LDAP_ATTR_DOMAIN,		"sambaDomainName"	},
 	{ LDAP_ATTR_OBJCLASS,		"objectClass"		},
 	{ LDAP_ATTR_ACB_INFO,		"sambaAcctFlags"	},
+	{ LDAP_ATTR_BAD_PWD_COUNT,	"sambaBadPwdCount"	},
+	{ LDAP_ATTR_LOCKOUT_TIME,	"sambaLockoutTime"	},
 	{ LDAP_ATTR_LIST_END,		NULL 			}
 };
 
Index: source/passdb/passdb.c
===================================================================
RCS file: /opt/cvs/prj/infra/serveur_proximite/samba/source/source/passdb/passdb.c,v
retrieving revision 1.1.1.1.4.1
retrieving revision 1.1.1.1.2.6
diff -u -r1.1.1.1.4.1 -r1.1.1.1.2.6
--- source/passdb/passdb.c	15 Sep 2003 09:59:16 -0000	1.1.1.1.4.1
+++ source/passdb/passdb.c	15 Sep 2003 14:24:04 -0000	1.1.1.1.2.6
@@ -78,6 +78,7 @@
 	user->private.pass_can_change_time  = (time_t)0;
 	user->private.logoff_time           = 
 	user->private.kickoff_time          = 
+	user->private.lockout_time          = (time_t)0;
 	user->private.pass_must_change_time = get_time_t_max();
 	user->private.unknown_3 = 0x00ffffff; 	/* don't know */
 	user->private.logon_divs = 168; 	/* hours per week */
@@ -85,6 +86,7 @@
 	memset(user->private.hours, 0xff, user->private.hours_len); /* available at all hours */
 	user->private.unknown_5 = 0x00000000; /* don't know */
 	user->private.unknown_6 = 0x000004ec; /* don't know */
+	user->private.bad_pwd_count = 0;
 
 	/* Some parts of samba strlen their pdb_get...() returns, 
 	   so this keeps the interface unchanged for now. */
@@ -1269,7 +1271,7 @@
  Marshall/unmarshall SAM_ACCOUNT structs.
  *********************************************************************/
 
-#define TDB_FORMAT_STRING       "ddddddBBBBBBBBBBBBddBBwdwdBdd"
+#define TDB_FORMAT_STRING       "dddddddBBBBBBBBBBBBddBBwdwdBddd"
 
 /**********************************************************************
  Intialize a SAM_ACCOUNT struct from a BYTE buffer of size len
@@ -1284,6 +1286,7 @@
 	uint32	logon_time,
 		logoff_time,
 		kickoff_time,
+		lockout_time,
 		pass_last_set_time,
 		pass_can_change_time,
 		pass_must_change_time;
@@ -1304,7 +1307,7 @@
 		fullname_len, homedir_len, logon_script_len,
 		profile_path_len, acct_desc_len, workstations_len;
 		
-	uint32	user_rid, group_rid, unknown_3, hours_len, unknown_5, unknown_6;
+	uint32	user_rid, group_rid, unknown_3, hours_len, unknown_5, unknown_6, bad_pwd_count;
 	uint16	acct_ctrl, logon_divs;
 	uint8	*hours;
 	static uint8	*lm_pw_ptr, *nt_pw_ptr;
@@ -1322,6 +1325,7 @@
 		&logon_time,
 		&logoff_time,
 		&kickoff_time,
+		&lockout_time,
 		&pass_last_set_time,
 		&pass_can_change_time,
 		&pass_must_change_time,
@@ -1347,7 +1351,8 @@
 		&hours_len,
 		&hourslen, &hours,
 		&unknown_5,
-		&unknown_6);
+		&unknown_6,
+		&bad_pwd_count);
 		
 	if (len == -1)  {
 		ret = False;
@@ -1357,6 +1362,7 @@
 	pdb_set_logon_time(sampass, logon_time, PDB_SET);
 	pdb_set_logoff_time(sampass, logoff_time, PDB_SET);
 	pdb_set_kickoff_time(sampass, kickoff_time, PDB_SET);
+	pdb_set_lockout_time(sampass, lockout_time, PDB_SET);
 	pdb_set_pass_can_change_time(sampass, pass_can_change_time, PDB_SET);
 	pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
 	pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
@@ -1426,6 +1432,7 @@
 	pdb_set_acct_ctrl(sampass, acct_ctrl, PDB_SET);
 	pdb_set_logon_divs(sampass, logon_divs, PDB_SET);
 	pdb_set_hours(sampass, hours, PDB_SET);
+	pdb_set_bad_pwd_count(sampass, bad_pwd_count, PDB_SET);
 
 done:
 
@@ -1460,11 +1467,12 @@
 	uint32	logon_time,
 		logoff_time,
 		kickoff_time,
+		lockout_time,
 		pass_last_set_time,
 		pass_can_change_time,
 		pass_must_change_time;
 
-	uint32  user_rid, group_rid;
+	uint32  user_rid, group_rid, bad_pwd_count;
 
 	const char *username;
 	const char *domain;
@@ -1500,6 +1508,7 @@
 	logon_time = (uint32)pdb_get_logon_time(sampass);
 	logoff_time = (uint32)pdb_get_logoff_time(sampass);
 	kickoff_time = (uint32)pdb_get_kickoff_time(sampass);
+	lockout_time = (uint32)pdb_get_lockout_time(sampass);
 	pass_can_change_time = (uint32)pdb_get_pass_can_change_time(sampass);
 	pass_must_change_time = (uint32)pdb_get_pass_must_change_time(sampass);
 	pass_last_set_time = (uint32)pdb_get_pass_last_set_time(sampass);
@@ -1598,13 +1607,15 @@
 	if (munged_dial)
 		munged_dial_len = strlen(munged_dial) +1;
 	else
-		munged_dial_len = 0;	
-		
+		munged_dial_len = 0;
+
+	
 	/* one time to get the size needed */
 	len = tdb_pack(NULL, 0,  TDB_FORMAT_STRING,
 		logon_time,
 		logoff_time,
 		kickoff_time,
+		lockout_time,
 		pass_last_set_time,
 		pass_can_change_time,
 		pass_must_change_time,
@@ -1630,7 +1641,8 @@
 		pdb_get_hours_len(sampass),
 		MAX_HOURS_LEN, pdb_get_hours(sampass),
 		pdb_get_unknown_5(sampass),
-		pdb_get_unknown_6(sampass));
+		pdb_get_unknown_6(sampass),
+		pdb_get_bad_pwd_count(sampass));
 
 
 	if (size_only)
@@ -1647,6 +1659,7 @@
 		logon_time,
 		logoff_time,
 		kickoff_time,
+		lockout_time,
 		pass_last_set_time,
 		pass_can_change_time,
 		pass_must_change_time,
@@ -1672,7 +1685,8 @@
 		pdb_get_hours_len(sampass),
 		MAX_HOURS_LEN, pdb_get_hours(sampass),
 		pdb_get_unknown_5(sampass),
-		pdb_get_unknown_6(sampass));
+		pdb_get_unknown_6(sampass),
+		pdb_get_bad_pwd_count(sampass));
 	
 	
 	/* check to make sure we got it correct */
Index: source/passdb/pdb_get_set.c
===================================================================
RCS file: /opt/cvs/prj/infra/serveur_proximite/samba/source/source/passdb/pdb_get_set.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.2.1
diff -u -r1.1.1.1 -r1.1.1.1.2.1
--- source/passdb/pdb_get_set.c	11 Sep 2003 15:45:32 -0000	1.1.1.1
+++ source/passdb/pdb_get_set.c	11 Sep 2003 15:58:28 -0000	1.1.1.1.2.1
@@ -339,6 +339,28 @@
 }
 
 /*********************************************************************
+ Get the user's bad password count.
+ ********************************************************************/
+uint32 pdb_get_bad_pwd_count (const SAM_ACCOUNT *sampass)
+{
+	if(sampass)
+		return (sampass->private.bad_pwd_count);
+	else
+		return (-1);
+}
+
+/*********************************************************************
+ Get the user's lockout_time.
+ ********************************************************************/
+time_t pdb_get_lockout_time (const SAM_ACCOUNT *sampass)
+{
+	if (sampass)
+		return (sampass->private.lockout_time);
+	else
+		return (-1);
+}
+
+/*********************************************************************
  Collection of set...() functions for SAM_ACCOUNT.
  ********************************************************************/
 
@@ -1122,4 +1144,30 @@
 		return False;
 
 	return True;
+}
+
+/*********************************************************************
+ Set the user's bad_pwd_count 
+ ********************************************************************/
+BOOL pdb_set_bad_pwd_count (SAM_ACCOUNT *sampass, uint32 badpwdcount, enum pdb_value_state flag)
+{
+	if (!sampass)
+		return False;
+	
+	sampass->private.bad_pwd_count = badpwdcount;
+	
+	return pdb_set_init_flags(sampass, PDB_BADPWDCOUNT, flag);
+}
+
+/********************************************************************
+ Set the user's lockout time
+ *******************************************************************/
+BOOL pdb_set_lockout_time (SAM_ACCOUNT *sampass, time_t mytime, enum pdb_value_state flag)
+{
+	if (!sampass)
+		return False;
+
+	sampass->private.lockout_time = mytime;
+
+	return pdb_set_init_flags(sampass, PDB_LOCKOUTTIME, flag);
 }
Index: source/passdb/pdb_ldap.c
===================================================================
RCS file: /opt/cvs/prj/infra/serveur_proximite/samba/source/source/passdb/pdb_ldap.c,v
retrieving revision 1.1.1.1.4.1
retrieving revision 1.1.1.1.2.3
diff -u -r1.1.1.1.4.1 -r1.1.1.1.2.3
--- source/passdb/pdb_ldap.c	15 Sep 2003 09:59:16 -0000	1.1.1.1.4.1
+++ source/passdb/pdb_ldap.c	15 Sep 2003 14:34:56 -0000	1.1.1.1.2.3
@@ -405,7 +405,8 @@
 			kickoff_time,
 			pass_last_set_time, 
 			pass_can_change_time, 
-			pass_must_change_time;
+			pass_must_change_time,
+			lockout_time;
 	pstring 	username, 
 			domain,
 			nt_username,
@@ -417,7 +418,8 @@
 			acct_desc,
 			munged_dial,
 			workstations;
-	uint32 		user_rid; 
+	uint32 		user_rid,
+			badpwdcount;
 	uint8 		smblmpwd[LM_HASH_LEN],
 			smbntpwd[NT_HASH_LEN];
 	uint16 		acct_ctrl = 0, 
@@ -585,6 +587,22 @@
 		pdb_set_pass_must_change_time(sampass, pass_must_change_time, PDB_SET);
 	}
 
+	if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry,
+			get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_BAD_PWD_COUNT), temp)) {	
+		/* leave as default */
+	} else {
+		badpwdcount = (uint32) atol(temp);
+		pdb_set_bad_pwd_count(sampass, badpwdcount, PDB_SET);
+	}
+	
+	if (!smbldap_get_single_attribute(ldap_state->smbldap_state->ldap_struct, entry, 
+			get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOCKOUT_TIME), temp)) {
+		/* leave as default */
+	} else {
+		lockout_time = (time_t) atol(temp);
+		pdb_set_lockout_time(sampass, lockout_time, PDB_SET);
+	}
+
 	/* recommend that 'gecos' and 'displayName' should refer to the same
 	 * attribute OID.  userFullName depreciated, only used by Samba
 	 * primary rules of LDAP: don't make a new attribute when one is already defined
@@ -878,6 +896,17 @@
 	if (need_update(sampass, PDB_MUSTCHANGETIME))
 		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_pwd_count(sampass));
+	if (need_update(sampass, PDB_BADPWDCOUNT))
+		smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
+			get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_BAD_PWD_COUNT), temp);
+
+	slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_lockout_time(sampass));
+	if (need_update(sampass, PDB_LOCKOUTTIME))
+		smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
+			get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOCKOUT_TIME), temp);
+
 
 	if ((pdb_get_acct_ctrl(sampass)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST))
 			|| (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_ONLY)) {
Index: source/passdb/pdb_mysql.c
===================================================================
RCS file: /opt/cvs/prj/infra/serveur_proximite/samba/source/source/passdb/pdb_mysql.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.2.1
diff -u -r1.1.1.1 -r1.1.1.1.2.1
--- source/passdb/pdb_mysql.c	11 Sep 2003 15:45:32 -0000	1.1.1.1
+++ source/passdb/pdb_mysql.c	11 Sep 2003 15:58:28 -0000	1.1.1.1.2.1
@@ -22,6 +22,10 @@
 #include <mysql/mysql.h>
 
 #define CONFIG_TABLE_DEFAULT				"user"
+
+#define CONFIG_BAD_PWD_COUNT_DEFAULT			"bad_pwd_count"
+#define CONFIG_LOCKOUT_TIME_DEFAULT			"lockout_time"
+
 #define CONFIG_LOGON_TIME_DEFAULT			"logon_time"
 #define CONFIG_LOGOFF_TIME_DEFAULT			"logoff_time"
 #define CONFIG_KICKOFF_TIME_DEFAULT			"kickoff_time"
@@ -262,6 +266,9 @@
 	pdb_set_unknown_5(u, xatol(row[27]), PDB_SET);
 	pdb_set_unknown_6(u, xatol(row[28]), PDB_SET);
 
+	pdb_set_bad_pwd_count(u, xatol(row[29]), PDB_SET);
+	pdb_set_lockout_time(u, xatol(row[30]), PDB_SET);
+      
 	return NT_STATUS_OK;
 }
 
@@ -278,7 +285,7 @@
 	}
 
 	asprintf(&query,
-			 "SELECT %s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s FROM %s",
+			 "SELECT %s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s FROM %s",
 			 config_value_read(data, "logon time column",
 							   CONFIG_LOGON_TIME_DEFAULT),
 			 config_value_read(data, "logoff time column",
@@ -337,6 +344,10 @@
 							   CONFIG_UNKNOWN_5_DEFAULT),
 			 config_value_read(data, "unknown 6 column",
 							   CONFIG_UNKNOWN_6_DEFAULT),
+			 config_value_read(data, "bad pwd count column",
+							   CONFIG_BAD_PWD_COUNT_DEFAULT),
+			 config_value_read(data, "lockout time column",
+							   CONFIG_LOCKOUT_TIME_DEFAULT),
 			 config_value(data, "table", CONFIG_TABLE_DEFAULT)
 				 );
 	DEBUG(5, ("Executing query %s\n", query));
@@ -442,7 +453,7 @@
 	}
 
 	asprintf(&query,
-			 "SELECT %s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s FROM %s WHERE %s = '%s'",
+			 "SELECT %s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s FROM %s WHERE %s = '%s'",
 			 config_value_read(data, "logon time column",
 							   CONFIG_LOGON_TIME_DEFAULT),
 			 config_value_read(data, "logoff time column",
@@ -501,6 +512,10 @@
 							   CONFIG_UNKNOWN_5_DEFAULT),
 			 config_value_read(data, "unknown 6 column",
 							   CONFIG_UNKNOWN_6_DEFAULT),
+			 config_value_read(data, "bad pwd count column",
+							   CONFIG_BAD_PWD_COUNT_DEFAULT),
+			 config_value_read(data, "lockout time column",
+							   CONFIG_LOCKOUT_TIME_DEFAULT),
 			 config_value(data, "table", CONFIG_TABLE_DEFAULT), field,
 			 esc_sname);
 	
@@ -747,6 +762,18 @@
 							pdb_get_logon_divs(newpwd));
 	}
 
+
+	pdb_mysql_int_field(methods, &query,
+						   config_value_write(data, "bad pwd count column",
+											  CONFIG_BAD_PWD_COUNT_DEFAULT),
+						   pdb_get_bad_pwd_count(newpwd));
+
+	pdb_mysql_int_field(methods, &query,
+						   config_value_write(data, "lockout time column",
+											  CONFIG_LOCKOUT_TIME_DEFAULT),
+						   pdb_get_lockout_time(newpwd));
+
+      
 	pdb_mysql_string_field(methods, &query,
 						   config_value_write(data, "user sid column",
 											  CONFIG_USER_SID_DEFAULT),
Index: source/passdb/pdb_xml.c
===================================================================
RCS file: /opt/cvs/prj/infra/serveur_proximite/samba/source/source/passdb/pdb_xml.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.2.2
diff -u -r1.1.1.1 -r1.1.1.1.2.2
--- source/passdb/pdb_xml.c	11 Sep 2003 15:45:32 -0000	1.1.1.1
+++ source/passdb/pdb_xml.c	16 Sep 2003 10:03:56 -0000	1.1.1.1.2.2
@@ -169,6 +169,16 @@
 							  atol(xmlNodeListGetString
 								   (doc, cur->xmlChildrenNode, 1)), PDB_SET);
 
+		else if (!strcmp(cur->name, "bad_pwd_count") && cur->ns == ns)
+			pdb_set_bad_pwd_count(u,
+							  atol(xmlNodeListGetString
+								   (doc, cur->xmlChildrenNode, 1)), PDB_SET);
+
+		else if (!strcmp(cur->name, "lockout_time") && cur->ns == ns)
+			pdb_set_lockout_time(u,
+							  atol(xmlNodeListGetString
+								   (doc, cur->xmlChildrenNode, 1)), PDB_SET);
+		
 		else if (!strcmp(cur->name, "homedir") && cur->ns == ns)
 			pdb_set_homedir(u,
 							xmlNodeListGetString(doc, cur->xmlChildrenNode,
@@ -410,7 +420,7 @@
 			   sid_to_string(sid_str, pdb_get_group_sid(u)));
 
 	if (pdb_get_init_flags(u, PDB_LOGONTIME) != PDB_DEFAULT)
-		xmlNewChild(user, data->ns, "login_time",
+		xmlNewChild(user, data->ns, "logon_time",
 					iota(pdb_get_logon_time(u)));
 
 	if (pdb_get_init_flags(u, PDB_LOGOFFTIME) != PDB_DEFAULT)
@@ -421,6 +431,10 @@
 		xmlNewChild(user, data->ns, "kickoff_time",
 					iota(pdb_get_kickoff_time(u)));
 
+	if (pdb_get_init_flags(u, PDB_LOCKOUTTIME) != PDB_DEFAULT)
+		xmlNewChild(user, data->ns, "lockout_time",
+					iota(pdb_get_lockout_time(u)));
+
 	if (pdb_get_domain(u) && strcmp(pdb_get_domain(u), ""))
 		xmlNewChild(user, data->ns, "domain", pdb_get_domain(u));
 
@@ -497,6 +511,9 @@
 
 	xmlNewChild(user, data->ns, "unknown_5", iota(pdb_get_unknown_5(u)));
 	xmlNewChild(user, data->ns, "unknown_6", iota(pdb_get_unknown_6(u)));
+	xmlNewChild(user, data->ns, "bad_pwd_count", iota(pdb_get_bad_pwd_count(u)));
+
+	
 	xmlSaveFile(data->location, data->doc);
 
 	return NT_STATUS_OK;
Index: source/rpc_server/srv_samr_util.c
===================================================================
RCS file: /opt/cvs/prj/infra/serveur_proximite/samba/source/source/rpc_server/srv_samr_util.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.2.1
diff -u -r1.1.1.1 -r1.1.1.1.2.1
--- source/rpc_server/srv_samr_util.c	11 Sep 2003 15:45:32 -0000	1.1.1.1
+++ source/rpc_server/srv_samr_util.c	11 Sep 2003 15:58:28 -0000	1.1.1.1.2.1
@@ -186,6 +186,8 @@
 	
 	DEBUG(10,("INFO_21 ACCT_CTRL: %08X -> %08X\n",pdb_get_acct_ctrl(to),from->acb_info));
 	if (from->acb_info != pdb_get_acct_ctrl(to)) {
+		if ((pdb_get_acct_ctrl(to) & ACB_AUTOLOCK) && !(from->acb_info & ACB_AUTOLOCK))
+			pdb_set_bad_pwd_count(to, 0, PDB_CHANGED);
 		pdb_set_acct_ctrl(to, from->acb_info, PDB_CHANGED);
 	}
 
@@ -390,7 +392,8 @@
 	}
 	
 	DEBUG(10,("INFO_23 ACCT_CTRL: %08X -> %08X\n",pdb_get_acct_ctrl(to),from->acb_info));
-	if (from->acb_info != pdb_get_acct_ctrl(to)) {
+	if ((from->acb_info != pdb_get_acct_ctrl(to)) && (from->acb_info)) {
+
 		pdb_set_acct_ctrl(to, from->acb_info, PDB_CHANGED);
 	}
 
Index: source/utils/pdbedit.c
===================================================================
RCS file: /opt/cvs/prj/infra/serveur_proximite/samba/source/source/utils/pdbedit.c,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.2.2
diff -u -r1.1.1.1 -r1.1.1.1.2.2
--- source/utils/pdbedit.c	11 Sep 2003 15:45:33 -0000	1.1.1.1
+++ source/utils/pdbedit.c	15 Sep 2003 14:34:56 -0000	1.1.1.1.2.2
@@ -47,6 +47,7 @@
 #define BIT_RESERV_7	0x00800000
 #define BIT_IMPORT	0x01000000
 #define BIT_EXPORT	0x02000000
+#define BIT_BADPWDRESET	0x04000000
 
 #define MASK_ALWAYS_GOOD	0x0000001F
 #define MASK_USER_GOOD		0x00401F00
@@ -144,6 +145,9 @@
 		tmp = pdb_get_kickoff_time(sam_pwent);
 		printf ("Kickoff time:         %s\n", tmp ? http_timestring(tmp) : "0");
 		
+		tmp = pdb_get_lockout_time(sam_pwent);
+		printf ("Lockout time:         %s\n", tmp ? http_timestring(tmp) : "0");
+		
 		tmp = pdb_get_pass_last_set_time(sam_pwent);
 		printf ("Password last set:    %s\n", tmp ? http_timestring(tmp) : "0");
 		
@@ -153,6 +157,8 @@
 		tmp = pdb_get_pass_must_change_time(sam_pwent);
 		printf ("Password must change: %s\n", tmp ? http_timestring(tmp) : "0");
 		
+		printf ("Bad password attempts: %d\n", pdb_get_bad_pwd_count(sam_pwent));
+		
 	} else if (smbpwdstyle) {
 		char lm_passwd[33];
 		char nt_passwd[33];
@@ -241,6 +247,7 @@
 			  const char *fullname, const char *homedir, 
 			  const char *drive, const char *script, 
 			  const char *profile, const char *account_control,
+			  const BOOL badpwd,
 			  const char *user_sid, const char *group_sid)
 {
 	SAM_ACCOUNT *sam_pwent=NULL;
@@ -282,6 +289,10 @@
 				  (pdb_get_acct_ctrl(sam_pwent) & not_settable) | newflag,
 				  PDB_CHANGED);
 	}
+
+	if (badpwd) 
+		pdb_set_bad_pwd_count(sam_pwent, 0, PDB_CHANGED);
+	
 	if (user_sid) {
 		DOM_SID u_sid;
 		if (!string_to_sid(&u_sid, user_sid)) {
@@ -548,6 +559,7 @@
 	static char *user_sid = NULL;
 	static char *group_sid = NULL;
 	static long int account_policy_value = 0;
+	static BOOL badpwd_reset = False;
 	BOOL account_policy_value_set = False;
 
 	struct pdb_context *bin;
@@ -578,6 +590,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},
+		{"badpwdcount-reset", 'z', POPT_ARG_NONE, &badpwd_reset, 0, "reset bad password count", NULL},
 		POPT_COMMON_SAMBA
 		POPT_TABLEEND
 	};
@@ -629,7 +642,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) +
+			(badpwd_reset ? BIT_BADPWDRESET : 0);
 
 	if (setparms & BIT_BACKEND) {
 		if (!NT_STATUS_IS_OK(make_pdb_context_string(&bdef, backend))) {
@@ -722,7 +736,12 @@
 	
 	/* mask out users options */
 	checkparms &= ~MASK_USER_GOOD;
-	
+
+	if (checkparms & BIT_BADPWDRESET) {
+		checkparms |= BIT_MODIFY;
+		checkparms &= ~BIT_BADPWDRESET;
+	}
+
 	/* account operation */
 	if ((checkparms & BIT_CREATE) || (checkparms & BIT_MODIFY) || (checkparms & BIT_DELETE)) {
 		/* check use of -u option */
@@ -758,6 +777,7 @@
 					      home_drive,
 					      logon_script,
 					      profile_path, account_control,
+					      badpwd_reset,
 					      user_sid, group_sid);
 		}
 	}


More information about the samba-technical mailing list