implementing password lockout

Aurélien Degrémont aurelien.degremont at idealx.com
Mon Jan 26 15:08:58 GMT 2004


I'll try to clarify the bad password count system..

First, it's sure a field is missing in our sam_account struct, we must 
store the lockout time, as my patch did it, it is necessary to unlock it 
when lock period is elapsed.
Concerning this, note that the "lockout time" is never provided in SAMR 
packets, even if NT do store it, it is only used internaly or during 
replication. We (with Richard) only see this once inside a NETLOGON 
struct, working on NT replication (Richard really need to post a patch 
only concerning all the breakthroughts on netlogon :)).

Second, note that the previously known unknow_3 field only apply to SAMR 
protocol, and as far as i know, netlogon doesn't implement something 
like this. So, i suppose each deltas sent during a replication are 
always totally filled. I cannot test this now. But the microsoft 
documentation you sent, explain this. 
(http://support.microsoft.com/default.aspx?scid=kb;en-us;297157).

We need, at least, to add 2 fields to sam accounts : a bad password 
count, and a lockout time.
I've attached my patch concerning this. It's 2-month old and doesn't 
manage ldap replication issues, but the other mecanisms are correct. 
Look at it.
Each DC maintains the number of bad password count. So, if the PDC is 
down, the BDC will look to the count and acct flags stored in their SAM db.

Aurélien

Jim McDonough wrote:

> Simo, thanks for clarifying that...but I still have a few issues to 
> clear up, since we don't (yet) have real windows replication:
>
> When the bad password count isn't replicated, if we're using LDAP 
> replication, we're going to replicate it, so we'll have to store a 
> time for the last bad password, no? We can't choose to selectively 
> replicate attributes sometimes, but not others. This is what Jianliang 
> has in his patch, and it makes sense to me.
>
> I still think we need a local version, though, because if we don't, 
> then if the PDC is down what happens when a user enters a bad 
> password? A correct password should be OK, but a bad password attempt...?
>
> ----------------------------
> Jim McDonough
> IBM Linux Technology Center
> Samba Team
> 6 Minuteman Drive
> Scarborough, ME 04074
> USA
>
> jmcd at us.ibm.com
> jmcd at samba.org
>
> Phone: (207) 885-5565
> IBM tie-line: 776-9984
>

-------------- next part --------------
diff -ruN samba-3.0.1pre1/examples/pdb/mysql/mysql.dump samba-badpwdcount-3.0.1pre1/examples/pdb/mysql/mysql.dump
--- samba-3.0.1pre1/examples/pdb/mysql/mysql.dump	2003-06-07 19:57:30.000000000 +0200
+++ samba-badpwdcount-3.0.1pre1/examples/pdb/mysql/mysql.dump	2003-11-17 10:11:10.000000000 +0100
@@ -31,5 +31,6 @@
 	logon_divs int(9),
 	hours_len int(9),
 	unknown_5 int(9),
-	unknown_6 int(9)
+	unknown_6 int(9),
+	lockout_time int(9)
 );
diff -ruN samba-3.0.1pre1/examples/pdb/mysql/smb.conf samba-badpwdcount-3.0.1pre1/examples/pdb/mysql/smb.conf
--- samba-3.0.1pre1/examples/pdb/mysql/smb.conf	2003-06-07 19:57:30.000000000 +0200
+++ samba-badpwdcount-3.0.1pre1/examples/pdb/mysql/smb.conf	2003-11-17 10:15:35.000000000 +0100
@@ -4,7 +4,7 @@
 security = domain
 domain logons = yes
 domain master = yes
-passdb backend = plugin:/usr/local/samba/lib/pdb_mysql.so:mysql
+passdb backend = mysql:samba1
 mysql:mysql host = rhonwyn
 mysql:mysql user = samba
 mysql:mysql password = ambas
diff -ruN samba-3.0.1pre1/source/auth/auth_sam.c samba-badpwdcount-3.0.1pre1/source/auth/auth_sam.c
--- samba-3.0.1pre1/source/auth/auth_sam.c	2003-10-10 20:08:34.000000000 +0200
+++ samba-badpwdcount-3.0.1pre1/source/auth/auth_sam.c	2003-11-17 10:57:40.000000000 +0100
@@ -407,6 +407,9 @@
 	NTSTATUS nt_status;
 	uint8 user_sess_key[16];
 	const uint8* lm_hash;
+	uint32 account_policy_lockout, account_policy_lockout_duration;
+	uint16 badpwdcount;
+	time_t lockout_time;
 
 	if (!user_info || !auth_context) {
 		return NT_STATUS_UNSUCCESSFUL;
@@ -429,13 +432,67 @@
 		pdb_free_sam(&sampass);
 		return NT_STATUS_NO_SUCH_USER;
 	}
-
+	
+	
+	/* if the account is locked, unlock it if lockout duration is expired */
+	if (pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK) {
+		lockout_time = 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();
+		}
+	}
+	
+	
 	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 = pdb_get_bad_password_count(sampass) + 1;
+			if (!pdb_set_bad_password_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;
 	}
+	
+	/* reset badpwdcount if account is normal*/
+	if (pdb_get_acct_ctrl(sampass) & ACB_NORMAL) {
+		if (!pdb_set_bad_password_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);
 
diff -ruN samba-3.0.1pre1/source/include/passdb.h samba-badpwdcount-3.0.1pre1/source/include/passdb.h
--- samba-3.0.1pre1/source/include/passdb.h	2003-10-10 20:08:34.000000000 +0200
+++ samba-badpwdcount-3.0.1pre1/source/include/passdb.h	2003-11-17 12:05:25.000000000 +0100
@@ -36,6 +36,7 @@
 	PDB_LOGONSCRIPT,
 	PDB_LOGONTIME,
 	PDB_LOGOFFTIME,
+	PDB_LOCKOUTTIME,
 	PDB_KICKOFFTIME,
 	PDB_CANCHANGETIME,
 	PDB_MUSTCHANGETIME,
@@ -105,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;
 		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 */
diff -ruN samba-3.0.1pre1/source/lib/smbldap.c samba-badpwdcount-3.0.1pre1/source/lib/smbldap.c
--- samba-3.0.1pre1/source/lib/smbldap.c	2003-09-11 20:05:44.000000000 +0200
+++ samba-badpwdcount-3.0.1pre1/source/lib/smbldap.c	2003-11-17 10:11:10.000000000 +0100
@@ -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 			}
 };
 
diff -ruN samba-3.0.1pre1/source/passdb/passdb.c samba-badpwdcount-3.0.1pre1/source/passdb/passdb.c
--- samba-3.0.1pre1/source/passdb/passdb.c	2003-10-10 20:08:36.000000000 +0200
+++ samba-badpwdcount-3.0.1pre1/source/passdb/passdb.c	2003-11-17 14:49:42.000000000 +0100
@@ -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 */
@@ -1303,6 +1304,7 @@
 	uint32	logon_time,
 		logoff_time,
 		kickoff_time,
+		lockout_time,
 		pass_last_set_time,
 		pass_can_change_time,
 		pass_must_change_time;
@@ -1342,6 +1344,7 @@
 		&logon_time,
 		&logoff_time,
 		&kickoff_time,
+		&lockout_time,
 		&pass_last_set_time,
 		&pass_can_change_time,
 		&pass_must_change_time,
@@ -1378,6 +1381,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);
@@ -1482,11 +1486,13 @@
 	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;
+	uint16	bad_pwd_count;
 
 	const char *username;
 	const char *domain;
@@ -1522,6 +1528,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);
@@ -1627,6 +1634,7 @@
 		logon_time,
 		logoff_time,
 		kickoff_time,
+		lockout_time,
 		pass_last_set_time,
 		pass_can_change_time,
 		pass_must_change_time,
@@ -1670,6 +1678,7 @@
 		logon_time,
 		logoff_time,
 		kickoff_time,
+		lockout_time,
 		pass_last_set_time,
 		pass_can_change_time,
 		pass_must_change_time,
diff -ruN samba-3.0.1pre1/source/passdb/pdb_get_set.c samba-badpwdcount-3.0.1pre1/source/passdb/pdb_get_set.c
--- samba-3.0.1pre1/source/passdb/pdb_get_set.c	2003-10-10 20:08:36.000000000 +0200
+++ samba-badpwdcount-3.0.1pre1/source/passdb/pdb_get_set.c	2003-11-17 10:11:11.000000000 +0100
@@ -347,6 +347,17 @@
 }
 
 /*********************************************************************
+ 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.
  ********************************************************************/
 
@@ -1141,3 +1152,16 @@
 
 	return True;
 }
+
+/********************************************************************
+ 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);
+}
diff -ruN samba-3.0.1pre1/source/passdb/pdb_ldap.c samba-badpwdcount-3.0.1pre1/source/passdb/pdb_ldap.c
--- samba-3.0.1pre1/source/passdb/pdb_ldap.c	2003-10-10 20:08:36.000000000 +0200
+++ samba-badpwdcount-3.0.1pre1/source/passdb/pdb_ldap.c	2003-11-17 14:52:05.000000000 +0100
@@ -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,
@@ -420,9 +421,9 @@
 	uint32 		user_rid; 
 	uint8 		smblmpwd[LM_HASH_LEN],
 			smbntpwd[NT_HASH_LEN];
-	uint16 		acct_ctrl = 0, 
+	uint16 	acct_ctrl = 0, 
 			logon_divs;
-	uint16 		bad_password_count = 0, 
+	uint16 	bad_password_count = 0, 
 			logon_count = 0;
 	uint32 hours_len;
 	uint8 		hours[MAX_HOURS_LEN];
@@ -587,6 +588,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_password_count(sampass, bad_pasword_count, 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
@@ -897,6 +914,17 @@
 		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_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_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)) {
 
diff -ruN samba-3.0.1pre1/source/passdb/pdb_mysql.c samba-badpwdcount-3.0.1pre1/source/passdb/pdb_mysql.c
--- samba-3.0.1pre1/source/passdb/pdb_mysql.c	2003-10-10 20:08:36.000000000 +0200
+++ samba-badpwdcount-3.0.1pre1/source/passdb/pdb_mysql.c	2003-11-17 14:44:21.000000000 +0100
@@ -25,6 +25,7 @@
 #define CONFIG_LOGON_TIME_DEFAULT			"logon_time"
 #define CONFIG_LOGOFF_TIME_DEFAULT			"logoff_time"
 #define CONFIG_KICKOFF_TIME_DEFAULT			"kickoff_time"
+#define CONFIG_LOCKOUT_TIME_DEFAULT			"lockout_time"
 #define CONFIG_PASS_LAST_SET_TIME_DEFAULT		"pass_last_set_time"
 #define CONFIG_PASS_CAN_CHANGE_TIME_DEFAULT		"pass_can_change_time"
 #define CONFIG_PASS_MUST_CHANGE_TIME_DEFAULT 		"pass_must_change_time"
@@ -269,6 +270,7 @@
 	pdb_set_bad_password_count(u, xatol(row[27]), PDB_SET);
 	pdb_set_logon_count(u, xatol(row[28]), PDB_SET);
 	pdb_set_unknown_6(u, xatol(row[29]), PDB_SET);
+	pdb_set_lockout_time(u, xatol(row[30]), PDB_SET);
 
 	return NT_STATUS_OK;
 }
@@ -286,7 +288,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,%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,%s FROM %s",
 			 config_value_read(data, "logon time column",
 							   CONFIG_LOGON_TIME_DEFAULT),
 			 config_value_read(data, "logoff time column",
@@ -347,6 +349,8 @@
 							   CONFIG_LOGON_COUNT_DEFAULT),
 			 config_value_read(data, "unknown 6 column",
 							   CONFIG_UNKNOWN_6_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));
@@ -452,7 +456,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,%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,%s FROM %s WHERE %s = '%s'",
 			 config_value_read(data, "logon time column",
 							   CONFIG_LOGON_TIME_DEFAULT),
 			 config_value_read(data, "logoff time column",
@@ -513,6 +517,8 @@
 							   CONFIG_LOGON_COUNT_DEFAULT),
 			 config_value_read(data, "unknown 6 column",
 							   CONFIG_UNKNOWN_6_DEFAULT),
+			 config_value_read(data, "lockout time column",
+							   CONFIG_LOCKOUT_TIME_DEFAULT),
 			 config_value(data, "table", CONFIG_TABLE_DEFAULT), field,
 			 esc_sname);
 	
@@ -761,6 +767,13 @@
 							pdb_get_logon_divs(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),
diff -ruN samba-3.0.1pre1/source/passdb/pdb_xml.c samba-badpwdcount-3.0.1pre1/source/passdb/pdb_xml.c
--- samba-3.0.1pre1/source/passdb/pdb_xml.c	2003-10-10 20:08:36.000000000 +0200
+++ samba-badpwdcount-3.0.1pre1/source/passdb/pdb_xml.c	2003-11-17 14:35:35.000000000 +0100
@@ -174,6 +174,11 @@
 							  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,
@@ -426,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));
 
diff -ruN samba-3.0.1pre1/source/rpc_server/srv_samr_util.c samba-badpwdcount-3.0.1pre1/source/rpc_server/srv_samr_util.c
--- samba-3.0.1pre1/source/rpc_server/srv_samr_util.c	2003-10-10 20:08:36.000000000 +0200
+++ samba-badpwdcount-3.0.1pre1/source/rpc_server/srv_samr_util.c	2003-11-17 14:52:51.000000000 +0100
@@ -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_password_count(to, 0, PDB_CHANGED);
 		pdb_set_acct_ctrl(to, from->acb_info, PDB_CHANGED);
 	}
 
@@ -395,7 +397,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 && (from->acb_info != pdb_get_acct_ctrl(to))) {
+
 		pdb_set_acct_ctrl(to, from->acb_info, PDB_CHANGED);
 	}
 
diff -ruN samba-3.0.1pre1/source/utils/pdbedit.c samba-badpwdcount-3.0.1pre1/source/utils/pdbedit.c
--- samba-3.0.1pre1/source/utils/pdbedit.c	2003-09-24 19:16:13.000000000 +0200
+++ samba-badpwdcount-3.0.1pre1/source/utils/pdbedit.c	2003-11-17 11:26:03.000000000 +0100
@@ -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_password_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_password_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