Implementation of Password Policy on Samba3.0 a22, and other
patches...
Jianliang Lu
j.lu at tiesse.com
Tue May 6 16:19:29 GMT 2003
Implementation of password policy on Samba3.0 alpha22
Copyright (C) Jianliang Lu 2003.
Written by Jianliang Lu <j.lu at tiesse.com> <luj at libero.it>
This program is free software; you can redistribute it and/or modify
it under the terms of GNU General Public License version 2 as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICOLAR PURPOSE. See the GNU
General Public License for more details.
Following are the descriptions of the implementations of password
policy on Samba 3.0 alpha22 with LDAP backend. The patches are
attached in the end.
- Password policy for "Minimum Password Age":
The period of time a password must be kept before the user can change
it. Do not allow immediate changes if a password history value will
be entered. The "Minimum Password Age" must be less than the
"Maximum Password Age".
To set the "Minimum Password Age" you can use:
pdbedit -P ""minimum password age" -V value
where value are expressed in seconds.
The pacth was made in passdb/pdb_get_set.c
- Password policy for "bad Password Attempt lockout"
The number of incorrect logon attempts that will cause the account to
be locked, except the members of "Domain Admins".
To set the "bad Password Attempt lockout":
pdbedit -P "bad lockout attempt" -V value.
To implement this function I have to extend the samba.schema of LDAP
that include a new integer SINGLE-VALUE attribute 'badPwAttempt'.
The implementations were mainly made in passdb/pdb_ldap.c
- Password policy for "Password History", or "Password Uniqueness":
The number of new passwords that must be used by a user before an old
password can be reused. For uniqueness to be effective, immediate
changes should not be allowed by the "Minimum Password Age" parameter.
To set "Password History":
pdbedit -P "password history" -V value
To implement this function, a new ASCII string MULTIVALUE attribute
'pwHistory' was added in the samba.schema. The implementations were
mainly made in passdb/pdb_ldap.c
- Set and reset the "Password must change time"
If selected, users must change (their own) passwords before they logon.
If cleared, users can logon without change their passwords.
To select or clear:
pdbedit -A value -u user, where value = 1 to select, 0 to clear.
or:
smbldap-usermod.pl -A value user
- Set and reset the "Password can change time"
If selected, users cannot change (their own) passwords (if the
"Password must change time" is not selected). If cleared, users can
change their own passwords.
To select or clear:
pdbedit -B value -u user, where value = 1 to select, 0 to clear.
or:
smbldap-usermod.pl -B value user
- Reset the "bad Password attempt count"
Clear the "bad Password Attempt lockout" count.
To reset the count:
pdbedit -z -u user
- Logon time:
The user's recent successful logon time. The patch was made in
auth/auth_sam.c.
To see the user's logon time:
pdbedit -u user -v
or
smbldap-usershow.pl user
Jianliang Lu
TieSse s.p.a.
Via Jervis, 60. 10015 Ivrea (To) - Italy
j.lu at tiesse.com
luj at libero.it
-------------- next part --------------
--- /source/auth/auth_sam.c Mon Feb 17 16:31:06 2003
+++ /source/auth/auth_sam.c.fix Tue May 6 11:14:55 2003
@@ -326,6 +326,12 @@
return NT_STATUS_ACCOUNT_DISABLED;
}
+ /* 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;
+ }
+
/* Test account expire time */
kickoff_time = pdb_get_kickoff_time(sampass);
@@ -414,6 +420,9 @@
NTSTATUS nt_status;
uint8 user_sess_key[16];
const uint8* lm_hash;
+ uint32 account_policy_lockout, badpwattempt;
+ GROUP_MAP map;
+ pstring grname;
if (!user_info || !auth_context) {
return NT_STATUS_UNSUCCESSFUL;
@@ -448,10 +457,51 @@
nt_status = sam_password_ok(auth_context, mem_ctx, sampass, user_info, user_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) {
+ badpwattempt = (uint32)pdb_get_bad_pw_attempt(sampass) + 1;
+ if (!pdb_set_bad_pw_attempt(sampass, badpwattempt, PDB_CHANGED))
+ DEBUG(1, ("Failed to set 'badPwAttempt' for user % s. \n",
+ user_info->internal_username.str));
+ account_policy_get(AP_BAD_ATTEMPT_LOCKOUT, &account_policy_lockout);
+ if (!pdb_getgrnam(&map, "Domain Admins", MAPPING_WITHOUT_PRIV))
+ DEBUG(1, ("auth_sam.c: Failed to get groupmap for Domain Admins"));
+ pstrcpy(grname, gidtoname(map.gid));
+/*
+ if ((badpwattempt >= account_policy_lockout) && !user_in_list(user_info->internal_username.str, lp_admin_users(-1), NULL, 0) && !user_in_group_list(user_info->internal_username.str, gidtoname(map.gid), NULL, 0))
+*/
+ if (account_policy_lockout && (badpwattempt >= account_policy_lockout) && !user_in_group_list(user_info->internal_username.str, grname, NULL, 0))
+ if (!pdb_set_acct_ctrl (sampass,
+ pdb_get_acct_ctrl(sampass) |ACB_AUTOLOCK,
+ PDB_CHANGED)) {
+ DEBUG(1, ("Failed to set 'disabled' flag 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 (pdb_get_acct_ctrl(sampass) &ACB_NORMAL){
+ if (!pdb_set_bad_pw_attempt(sampass, 0, PDB_CHANGED))
+ DEBUG(1, ("Failed to set 'badPwAttempt' 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 fialed!\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();
+ }
+
if (!NT_STATUS_IS_OK(nt_status = make_server_info_sam(server_info, sampass))) {
DEBUG(0,("check_sam_security: make_server_info_sam() failed with '%s'\n", nt_errstr(nt_status)));
return nt_status;
-------------- next part --------------
--- /source/passdb/passdb.c Mon Feb 24 16:12:31 2003
+++ /source/passdb/passdb.c.fix Tue May 6 11:14:55 2003
@@ -60,6 +60,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_pw_attempt = 0; /* bad password attemp count */
/* Some parts of samba strlen their pdb_get...() returns,
so this keeps the interface unchanged for now. */
@@ -1127,6 +1128,11 @@
}
if (local_flags & LOCAL_ADD_USER) {
+ if (!pdb_set_pass_must_change_time (sam_pass, 0, PDB_CHANGED)) {
+ slprintf(err_str, err_str_len-1, "Failed to set must change time for user %s.\n", user_name);
+ pdb_free_sam(&sam_pass);
+ return False;
+ }
if (pdb_add_sam_account(sam_pass)) {
slprintf(msg_str, msg_str_len-1, "Added user %s.\n", user_name);
pdb_free_sam(&sam_pass);
-------------- next part --------------
--- /source/passdb/pdb_get_set.c Thu Jan 9 20:05:59 2003
+++ /source/passdb/pdb_get_set.c.fix Tue May 6 11:14:55 2003
@@ -131,6 +131,15 @@
return (NULL);
}
+const uint8* pdb_get_pw_history (const SAM_ACCOUNT *sampass)
+{
+ if (sampass) {
+ return ((uint8*)sampass->private.nt_pw_his);
+ }
+ else
+ return (NULL);
+}
+
const uint8* pdb_get_lanman_passwd (const SAM_ACCOUNT *sampass)
{
if (sampass) {
@@ -172,6 +181,14 @@
return (NULL);
}
+uint32 pdb_get_bad_pw_attempt (const SAM_ACCOUNT *sampass)
+{
+ if (sampass)
+ return (sampass->private.bad_pw_attempt);
+ else
+ return (-1);
+}
+
/**
* Get flags showing what is initalised in the SAM_ACCOUNT
* @param sampass the SAM_ACCOUNT in question
@@ -964,6 +981,31 @@
return pdb_set_init_flags(sampass, PDB_NTPASSWD, flag);
}
+
+/*********************************************************************
+ Set the user's password history hash.
+ ********************************************************************/
+
+BOOL pdb_set_pw_history (SAM_ACCOUNT *sampass, const uint8 * pwd, int historyLen, enum pdb_value_state flag)
+{
+ if (!sampass)
+ return False;
+
+ if (historyLen > 0){
+ if (pwd){
+ sampass->private.nt_pw_his = (uint *) talloc_memdup(sampass->mem_ctx, pwd, historyLen*16);
+ if (!sampass->private.nt_pw_his) {
+ DEBUG(0, ("pdb_set_nt_pw_his: talloc_memdup() failed!\n"));
+ return False;
+ }
+ }else {
+ sampass->private.nt_pw_his = NULL;
+ }
+ }
+
+ return pdb_set_init_flags(sampass, PDB_PWHISTORY, flag);
+}
+
/*********************************************************************
Set the user's LM hash.
********************************************************************/
@@ -1038,6 +1080,16 @@
return pdb_set_init_flags(sampass, PDB_UNKNOWN6, flag);
}
+BOOL pdb_set_bad_pw_attempt (SAM_ACCOUNT *sampass, uint32 badpwattempt, enum pdb_value_state flag)
+{
+ if (!sampass)
+ return False;
+
+ sampass->private.bad_pw_attempt = badpwattempt;
+
+ return pdb_set_init_flags(sampass, PDB_BADPWATTEMPT, flag);
+}
+
BOOL pdb_set_hours (SAM_ACCOUNT *sampass, const uint8 *hours, enum pdb_value_state flag)
{
if (!sampass)
@@ -1064,6 +1116,7 @@
BOOL pdb_set_pass_changed_now (SAM_ACCOUNT *sampass)
{
uint32 expire;
+ uint32 min_age;
if (!sampass)
return False;
@@ -1071,17 +1124,29 @@
if (!pdb_set_pass_last_set_time (sampass, time(NULL), PDB_CHANGED))
return False;
- if (!account_policy_get(AP_MAX_PASSWORD_AGE, &expire)
- || (expire==(uint32)-1)) {
- if (!pdb_set_pass_must_change_time (sampass, get_time_t_max(), PDB_CHANGED))
- return False;
- } else {
- if (!pdb_set_pass_must_change_time (sampass,
- pdb_get_pass_last_set_time(sampass)
- + expire, PDB_CHANGED))
- return False;
- }
+ if (pdb_get_acct_ctrl(sampass)&(ACB_NORMAL)){
+ if (!account_policy_get(AP_MAX_PASSWORD_AGE, &expire)
+ || (expire==(uint32)-1)) {
+ if (!pdb_set_pass_must_change_time (sampass, get_time_t_max(), PDB_CHANGED))
+ return False;
+ } else {
+ if (!pdb_set_pass_must_change_time (sampass,
+ pdb_get_pass_last_set_time(sampass)
+ + expire, PDB_CHANGED))
+ return False;
+ }
+ if (!account_policy_get(AP_MIN_PASSWORD_AGE, &min_age)
+ || (min_age==(uint32)-1)) {
+ if (!pdb_set_pass_can_change_time (sampass, 0, PDB_CHANGED))
+ return False;
+ } else {
+ if (!pdb_set_pass_can_change_time (sampass,
+ pdb_get_pass_last_set_time(sampass)
+ + min_age, PDB_CHANGED))
+ return False;
+ }
+ }
return True;
}
@@ -1094,10 +1159,19 @@
{
uchar new_lanman_p16[16];
uchar new_nt_p16[16];
+ uchar *pwhistory;
+ uchar nt_pw[16];
+ uchar * ntpw;
+ int pwHistLen;
+
if (!sampass || !plaintext)
return False;
-
+
+ ntpw = pdb_get_nt_passwd(sampass);
+ if (ntpw)
+ memcpy ((uchar *)nt_pw, (uchar *)ntpw, 16);
+
nt_lm_owf_gen (plaintext, new_nt_p16, new_lanman_p16);
if (!pdb_set_nt_passwd (sampass, new_nt_p16, PDB_CHANGED))
@@ -1112,5 +1186,19 @@
if (!pdb_set_pass_changed_now (sampass))
return False;
+ if (pdb_get_acct_ctrl(sampass) & ACB_NORMAL) {
+ account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen);
+ if (pwHistLen > 0){
+ pwhistory = pdb_get_pw_history (sampass);
+ if (pwhistory){
+ memmove((uchar *) (pwhistory + 16), pwhistory, (pwHistLen -1)*16 );
+ memcpy((uchar *)pwhistory, (uchar *)nt_pw, 16);
+ pdb_set_pw_history (sampass, pwhistory, pwHistLen, PDB_CHANGED);
+ }
+ else {
+ DEBUG (100,("pdb_get_set.c: pdb_set_plaintext_passwd: pwhistory was NULL!\n"));
+ }
+ }
+ }
return True;
}
-------------- next part --------------
--- /source/passdb/pdb_ldap.c Thu Mar 13 12:27:01 2003
+++ /source/passdb/pdb_ldap.c.fix Tue May 6 11:14:55 2003
@@ -149,11 +149,11 @@
"logoffTime", "kickoffTime", "cn",
"pwdCanChange", "pwdMustChange",
"displayName", "homeDrive",
- "smbHome", "scriptPath",
+ "smbHome", "scriptPath", "badPwAttempt",
"profilePath", "description",
"userWorkstations", "rid",
"primaryGroupID", "lmPassword",
- "ntPassword", "acctFlags",
+ "ntPassword", "acctFlags", "pwHistory",
"domain", "objectClass",
"uidNumber", "gidNumber",
"homeDirectory", NULL };
@@ -770,6 +770,31 @@
return True;
}
+/*******************************************************************
+search an attribute and return the value found.
+******************************************************************/
+static BOOL get_single_attribute_multivalue (LDAP * ldap_struct, LDAPMessage * entry,
+ const char *attribute, char *value, int len, int * count)
+{
+ char **values;
+ int i;
+
+ if ((values = ldap_get_values (ldap_struct, entry, attribute)) == NULL) {
+ value = NULL;
+ DEBUG (10, ("get_single_attribute_multivalue: [%s] = [<does not exist>]\n", attribute));
+ return False;
+ }
+
+ for (i = 0; (values[i] != NULL) && (i < len); i++)
+ pstrcpy((char *) (value + i*sizeof(pstring)), values[i]);
+ *count = i;
+ ldap_value_free(values);
+#ifdef DEBUG_PASSWORDS
+ DEBUG (100, ("get_single_attribute_multivalue: [%s] = [%s]\n", attribute, value));
+#endif
+ return True;
+}
+
/************************************************************************
Routine to manage the LDAPMod structure array
manage memory used by the array, by each struct, and values
@@ -927,7 +952,8 @@
workstations;
struct passwd *pw;
uint32 user_rid,
- group_rid;
+ group_rid,
+ badpwattempt;
uint8 smblmpwd[LM_HASH_LEN],
smbntpwd[NT_HASH_LEN];
uint16 acct_ctrl = 0,
@@ -937,7 +963,9 @@
pstring temp;
uid_t uid = -1;
gid_t gid = getegid();
-
+ char *temp1;
+ uint8 *pwhist;
+ int i, pwcount, pwHistLen;
/*
* do a little initialization
@@ -980,6 +1008,7 @@
get_single_attribute(ldap_state->ldap_struct, entry, "rid", temp);
user_rid = (uint32)atol(temp);
+
pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET);
if (!get_single_attribute(ldap_state->ldap_struct, entry, "primaryGroupID", temp)) {
@@ -1037,6 +1066,12 @@
pdb_set_pass_last_set_time(sampass, pass_last_set_time, PDB_SET);
}
+ if (!get_single_attribute(ldap_state->ldap_struct, entry, "badPwAttempt", temp)) {
+ /* leave as default */
+ } else {
+ badpwattempt = (uint32)atol(temp);
+ pdb_set_bad_pw_attempt(sampass, badpwattempt, PDB_SET);
+ }
if (!get_single_attribute(ldap_state->ldap_struct, entry, "logonTime", temp)) {
/* leave as default */
} else {
@@ -1166,6 +1201,32 @@
ZERO_STRUCT(smbntpwd);
}
+ account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen);
+ if (pwHistLen > 0){
+ if ((temp1 = (char *) malloc(sizeof(pstring) * pwHistLen)) == NULL) {
+ DEBUG(0, ("pdb_ldap.c: init_sam_from_ldap: malloc failed!\n"));
+ return False;
+ }
+ if ((pwhist = (uint8 *) malloc(16 * pwHistLen)) == NULL){
+ DEBUG(0, ("pdb_ldap.c: init_sam_from_ldap: malloc failed!\n"));
+ return False;
+ }
+ memset((uint8 *) pwhist, 0, 16*pwHistLen);
+ if (!get_single_attribute_multivalue (ldap_state->ldap_struct, entry, "pwHistory", temp1, pwHistLen, &pwcount)) {
+ /* leave as default */
+ } else {
+ for (i = 0; (i < pwHistLen) && (i < pwcount); i++){
+ pdb_gethexpwd((char *)(temp1 + i*sizeof(pstring)), smbntpwd);
+ memcpy((unsigned char *) (pwhist + i*16), smbntpwd, 16);
+ ZERO_STRUCT(smbntpwd);
+ }
+ }
+ if (!pdb_set_pw_history(sampass, pwhist, pwHistLen, PDB_SET))
+ return False;
+ SAFE_FREE (temp1);
+ SAFE_FREE (pwhist);
+ }
+
if (!get_single_attribute (ldap_state->ldap_struct, entry, "acctFlags", temp)) {
acct_ctrl |= ACB_NORMAL;
} else {
@@ -1210,6 +1271,8 @@
{
pstring temp;
uint32 rid;
+ uint8 * temp1;
+ int i, pwHistLen;
if (mods == NULL || sampass == NULL) {
DEBUG(0, ("init_ldap_from_sam: NULL parameters found!\n"));
@@ -1309,6 +1372,11 @@
make_a_mod(mods, ldap_op, "logonTime", temp);
}
+ if (need_ldap_mod(pdb_add, sampass, PDB_BADPWATTEMPT)) {
+ slprintf(temp, sizeof(temp) - 1, "%i", pdb_get_bad_pw_attempt(sampass));
+ make_a_mod(mods, ldap_op, "badPwAttempt", temp);
+ }
+
if (need_ldap_mod(pdb_add, sampass, PDB_LOGOFFTIME)) {
slprintf(temp, sizeof(temp) - 1, "%li", pdb_get_logoff_time(sampass));
make_a_mod(mods, ldap_op, "logoffTime", temp);
@@ -1342,6 +1410,18 @@
pdb_sethexpwd (temp, pdb_get_nt_passwd(sampass), pdb_get_acct_ctrl(sampass));
make_a_mod (mods, ldap_op, "ntPassword", temp);
}
+
+ if (need_ldap_mod(pdb_add, sampass, PDB_PWHISTORY)) {
+ account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen);
+ temp1 = (uint8 *) pdb_get_pw_history(sampass);
+ if (temp1 != NULL)
+ for (i=0; i< pwHistLen; i++){
+ pdb_sethexpwd (temp, (uint8 *)(temp1 + i*16), 0);
+ if (!strncmp(temp,"0000000000",10))
+ break;
+ make_a_mod (mods, ldap_op, "pwHistory", temp);
+ }
+ }
if (need_ldap_mod(pdb_add, sampass, PDB_PASSLASTSET)) {
slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_last_set_time(sampass));
-------------- next part --------------
--- /source/utils/pdbedit.c Fri Feb 14 23:34:38 2003
+++ /source/utils/pdbedit.c.fix Tue May 6 11:14:55 2003
@@ -47,6 +47,9 @@
#define BIT_RESERV_7 0x00800000
#define BIT_IMPORT 0x01000000
#define BIT_EXPORT 0x02000000
+#define BIT_BADPWRESET 0x04000000
+#define BIT_PWCANCHG 0x08000000
+#define BIT_PWMUSTCHG 0x10000000
#define MASK_ALWAYS_GOOD 0x0000001F
#define MASK_USER_GOOD 0x00401F00
@@ -136,6 +139,7 @@
tmp = pdb_get_pass_must_change_time(sam_pwent);
printf ("Password must change: %s\n", tmp ? http_timestring(tmp) : "0");
+ printf ("Bad Password Attempt: %d\n", pdb_get_bad_pw_attempt(sam_pwent));
} else if (smbpwdstyle) {
if (IS_SAM_UNIX_USER(sam_pwent)) {
char lm_passwd[33];
@@ -227,6 +231,7 @@
return 0;
}
+
/*********************************************************
Set User Info
**********************************************************/
@@ -234,10 +239,12 @@
static int set_user_info (struct pdb_context *in, const char *username,
const char *fullname, const char *homedir,
const char *drive, const char *script,
- const char *profile, const char *account_control)
+ const char *profile, const char *account_control,
+ const BOOL badpw, const long pwchg, const long pwmust)
{
SAM_ACCOUNT *sam_pwent=NULL;
BOOL ret;
+ long winmagic = 2147483647;
pdb_init_sam(&sam_pwent);
@@ -275,6 +282,29 @@
(pdb_get_acct_ctrl(sam_pwent) & not_settable) | newflag,
PDB_CHANGED);
}
+
+ switch (pwchg) {
+ case 0:
+ pdb_set_pass_can_change_time(sam_pwent, winmagic, PDB_CHANGED);
+ break;
+ case 1:
+ pdb_set_pass_can_change_time(sam_pwent, 0, PDB_CHANGED);
+ break;
+ default:
+ }
+
+ switch (pwmust) {
+ case 0:
+ pdb_set_pass_must_change_time(sam_pwent, winmagic, PDB_CHANGED);
+ break;
+ case 1:
+ pdb_set_pass_must_change_time(sam_pwent, 0, PDB_CHANGED);
+ break;
+ default:
+ }
+
+ if (badpw)
+ pdb_set_bad_pw_attempt(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);
@@ -482,6 +512,11 @@
static char *account_policy = NULL;
static long int account_policy_value = 0;
BOOL account_policy_value_set = False;
+ static long pw_canchg = 2147483647;
+ static long pw_mustchg = 2147483647;
+ static BOOL badpw_reset = False;
+ BOOL pw_canchg_set = False;
+ BOOL pw_mustchg_set = False;
struct pdb_context *bin;
struct pdb_context *bout;
@@ -508,6 +543,9 @@
{"account-policy", 'P', POPT_ARG_STRING, &account_policy, 0,"value of an account policy (like maximum password age)",NULL},
{"value", 'V', POPT_ARG_LONG, &account_policy_value, 'V',"set the account policy to this value", NULL},
{"account-control", 'c', POPT_ARG_STRING, &account_control, 0, "Values of account control", NULL},
+ {"pwcanchg", 'A', POPT_ARG_LONG, &pw_canchg, 'A', "can change password ? 0 if no, 1 if yes", NULL},
+ {"pwmustchg", 'B', POPT_ARG_LONG, &pw_mustchg, 'B', "must change password ? 0 if no, 1 if yes", NULL},
+ {"badpwreset", 'z', POPT_ARG_NONE, &badpw_reset, 0, "reset bad password count", NULL},
{ NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_debug },
{ NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_configfile },
{0,0,0,0}
@@ -523,6 +561,13 @@
case 'V':
account_policy_value_set = True;
break;
+ case 'A':
+ fprintf(stderr, "A set.\n");
+ pw_canchg_set = True;
+ break;
+ case 'B':
+ pw_mustchg_set = True;
+ break;
}
}
@@ -557,7 +602,10 @@
(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) +
+ (pw_canchg_set ? BIT_PWCANCHG : 0) +
+ (pw_mustchg_set ? BIT_PWMUSTCHG : 0) +
+ (badpw_reset ? BIT_BADPWRESET : 0);
if (setparms & BIT_BACKEND) {
if (!NT_STATUS_IS_OK(make_pdb_context_string(&bdef, backend))) {
@@ -647,6 +695,11 @@
/* mask out users options */
checkparms &= ~MASK_USER_GOOD;
+ if ((checkparms & BIT_BADPWRESET) || (checkparms & BIT_PWCANCHG) || (checkparms & BIT_PWMUSTCHG)){
+ checkparms |= BIT_MODIFY;
+ checkparms &= ~(BIT_BADPWRESET + BIT_PWCANCHG + BIT_PWMUSTCHG);
+ }
+
/* account operation */
if ((checkparms & BIT_CREATE) || (checkparms & BIT_MODIFY) || (checkparms & BIT_DELETE)) {
/* check use of -u option */
@@ -681,7 +734,8 @@
home_dir,
home_drive,
logon_script,
- profile_path, account_control);
+ profile_path, account_control,
+ badpw_reset, pw_canchg, pw_mustchg);
}
}
-------------- next part --------------
--- /source/include/smb.h Thu Feb 27 22:21:08 2003
+++ /source/include/smb.h.fix Tue May 6 11:14:55 2003
@@ -613,6 +613,8 @@
PDB_UNKNOWN6,
PDB_LMPASSWD,
PDB_NTPASSWD,
+ PDB_BADPWATTEMPT,
+ PDB_PWHISTORY,
/* this must be the last element */
PDB_COUNT,
@@ -665,7 +667,7 @@
const char * workstations; /* login from workstations string */
const char * unknown_str ; /* don't know what this is, yet. */
const char * munged_dial ; /* munged path name and dial-back tel number */
-
+
uid_t uid; /* this is a unix uid_t */
gid_t gid; /* this is a unix gid_t */
DOM_SID user_sid; /* Primary User SID */
@@ -684,6 +686,8 @@
uint32 unknown_5; /* 0x0002 0000 */
uint32 unknown_6; /* 0x0000 04ec */
+ uint32 bad_pw_attempt; /* count of bad password attempt */
+ uint8 *nt_pw_his; /* password history */
} private;
/* Lets see if the remaining code can get the hint that you
-------------- next part --------------
--- //source/rpc_server/srv_samr_util.c Mon Jan 6 16:40:38 2003
+++ //source/rpc_server/srv_samr_util.c.fix Tue May 6 11:14:55 2003
@@ -182,6 +182,9 @@
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_pw_attempt(to, 0, PDB_CHANGED);
+
pdb_set_acct_ctrl(to, from->acb_info, PDB_CHANGED);
}
@@ -383,7 +386,7 @@
}
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);
}
-------------- next part --------------
--- /examples/LDAP/samba.schema Mon Jan 6 17:39:40 2003
+++ /examples/LDAP/samba.schema.fix Tue May 6 11:14:55 2003
@@ -64,6 +64,11 @@
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.19 NAME 'badPwAttempt'
+ DESC 'NT badPwAttempt'
+ EQUALITY integerMatch
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
##
## string settings
##
@@ -110,6 +115,11 @@
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.20 NAME 'pwHistory'
+ DESC 'NT Passwd'
+ EQUALITY caseIgnoreIA5Match
+ SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} )
+
##
## The smbPasswordEntry objectclass has been depreciated in favor of the
## sambaAccount objectclass
@@ -134,19 +144,19 @@
objectclass ( 1.3.6.1.4.1.7165.2.2.3 NAME 'sambaAccount' SUP top AUXILIARY
DESC 'Samba Auxilary Account'
MUST ( uid $ rid )
- MAY ( cn $ lmPassword $ ntPassword $ pwdLastSet $ logonTime $
+ MAY ( cn $ lmPassword $ ntPassword $ pwdLastSet $ logonTime $ badPwAttempt $
logoffTime $ kickoffTime $ pwdCanChange $ pwdMustChange $ acctFlags $
displayName $ smbHome $ homeDrive $ scriptPath $ profilePath $
- description $ userWorkstations $ primaryGroupID $ domain ))
+ pwHistory $ description $ userWorkstations $ primaryGroupID $ domain ))
##
## Used for Winbind experimentation
##
-#objectclass ( 1.3.6.1.4.1.7165.1.2.2.3 NAME 'uidPool' SUP top AUXILIARY
-# DESC 'Pool for allocating UNIX uids'
-# MUST ( uidNumber $ cn ) )
-
-#objectclass ( 1.3.6.1.4.1.7165.1.2.2.4 NAME 'gidPool' SUP top AUXILIARY
-# DESC 'Pool for allocating UNIX gids'
-# MUST ( gidNumber $ cn ) )
+objectclass ( 1.3.6.1.4.1.7165.1.2.2.3 NAME 'uidPool' SUP top AUXILIARY
+ DESC 'Pool for allocating UNIX uids'
+ MUST ( uidNumber $ cn ) )
+
+objectclass ( 1.3.6.1.4.1.7165.1.2.2.4 NAME 'gidPool' SUP top AUXILIARY
+ DESC 'Pool for allocating UNIX gids'
+ MUST ( gidNumber $ cn ) )
More information about the samba-technical
mailing list