Index: source/passdb/pdb_get_set.c =================================================================== RCS file: /data/cvs/samba/source/passdb/pdb_get_set.c,v retrieving revision 1.26.2.4 diff -u -r1.26.2.4 pdb_get_set.c --- passdb/pdb_get_set.c 7 Nov 2003 17:36:50 -0000 1.26.2.4 +++ passdb/pdb_get_set.c 5 Feb 2004 14:43:53 -0000 @@ -933,7 +933,11 @@ data_blob_clear_free(&sampass->private.nt_pw); - sampass->private.nt_pw = data_blob(pwd, NT_HASH_LEN); + if (pwd) { + sampass->private.nt_pw = data_blob(pwd, NT_HASH_LEN); + } else { + sampass->private.nt_pw = data_blob(NULL, 0); + } return pdb_set_init_flags(sampass, PDB_NTPASSWD, flag); } @@ -949,7 +953,11 @@ data_blob_clear_free(&sampass->private.lm_pw); - sampass->private.lm_pw = data_blob(pwd, LM_HASH_LEN); + if (pwd) { + sampass->private.lm_pw = data_blob(pwd, LM_HASH_LEN); + } else { + sampass->private.lm_pw = data_blob(NULL, 0); + } return pdb_set_init_flags(sampass, PDB_LMPASSWD, flag); } Index: source/passdb/pdb_interface.c =================================================================== RCS file: /data/cvs/samba/source/passdb/pdb_interface.c,v retrieving revision 1.47.2.3 diff -u -r1.47.2.3 pdb_interface.c --- passdb/pdb_interface.c 8 Sep 2003 14:13:34 -0000 1.47.2.3 +++ passdb/pdb_interface.c 5 Feb 2004 14:43:54 -0000 @@ -36,6 +36,44 @@ static struct pdb_init_function_entry *pdb_find_backend_entry(const char *name); +/******************************************************************* + Clean up uninitialised passwords. The only way to tell + that these values are not 'real' is that they do not + have a valid last set time. Instead, the value is fixed at 0. + Therefore we use that as the key for 'is this a valid password'. + However, it is perfectly valid to have a 'default' last change + time, such LDAP with a missing attribute would produce. +********************************************************************/ + +static void pdb_force_pw_initialization(SAM_ACCOUNT *pass) +{ + const char *lm_pwd, *nt_pwd; + + /* only reset a password if the last set time has been + explicitly been set to zero. A default last set time + is ignored */ + + if ( (pdb_get_init_flags(pass, PDB_PASSLASTSET) != PDB_DEFAULT) + && (pdb_get_pass_last_set_time(pass) == 0) ) + { + + if (pdb_get_init_flags(pass, PDB_LMPASSWD) != PDB_DEFAULT) + { + lm_pwd = pdb_get_lanman_passwd(pass); + if (lm_pwd) + pdb_set_lanman_passwd(pass, NULL, PDB_SET); + } + if (pdb_get_init_flags(pass, PDB_NTPASSWD) != PDB_DEFAULT) + { + nt_pwd = pdb_get_nt_passwd(pass); + if (nt_pwd) + pdb_set_nt_passwd(pass, NULL, PDB_SET); + } + } + + return; +} + NTSTATUS smb_register_passdb(int version, const char *name, pdb_init_function init) { struct pdb_init_function_entry *entry = backends; @@ -141,6 +179,7 @@ context->pwent_methods->setsampwent(context->pwent_methods, False); } user->methods = context->pwent_methods; + pdb_force_pw_initialization(user); return ret; } @@ -156,6 +195,7 @@ curmethods = context->pdb_methods; while (curmethods){ if (NT_STATUS_IS_OK(ret = curmethods->getsampwnam(curmethods, sam_acct, username))) { + pdb_force_pw_initialization(sam_acct); sam_acct->methods = curmethods; return ret; } @@ -179,6 +219,7 @@ while (curmethods){ if (NT_STATUS_IS_OK(ret = curmethods->getsampwsid(curmethods, sam_acct, sid))) { + pdb_force_pw_initialization(sam_acct); sam_acct->methods = curmethods; return ret; } @@ -191,12 +232,26 @@ static NTSTATUS context_add_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct) { NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + const char *lm_pw, *nt_pw; + uint16 acb_flags; if ((!context) || (!context->pdb_methods)) { DEBUG(0, ("invalid pdb_context specified!\n")); return ret; } + /* disable acccounts with no passwords (that has not + been allowed by the ACB_PWNOTREQ bit */ + + lm_pw = pdb_get_lanman_passwd( sam_acct ); + nt_pw = pdb_get_lanman_passwd( sam_acct ); + acb_flags = pdb_get_acct_ctrl( sam_acct ); + if ( !lm_pw && !nt_pw && !(acb_flags&ACB_PWNOTREQ) ) { + acb_flags |= ACB_DISABLED; + pdb_set_acct_ctrl( sam_acct, acb_flags, PDB_SET ); + pdb_set_init_flags(sam_acct, PDB_ACCTCTRL, PDB_SET); + } + /** @todo This is where a 're-read on add' should be done */ /* We now add a new account to the first database listed. * Should we? */ @@ -207,6 +262,8 @@ static NTSTATUS context_update_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct) { NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + const char *lm_pw, *nt_pw; + uint16 acb_flags; if (!context) { DEBUG(0, ("invalid pdb_context specified!\n")); @@ -218,6 +275,18 @@ return ret; } + /* disable acccounts with no passwords (that has not + been allowed by the ACB_PWNOTREQ bit */ + + lm_pw = pdb_get_lanman_passwd( sam_acct ); + nt_pw = pdb_get_lanman_passwd( sam_acct ); + acb_flags = pdb_get_acct_ctrl( sam_acct ); + if ( !lm_pw && !nt_pw && !(acb_flags&ACB_PWNOTREQ) ) { + acb_flags |= ACB_DISABLED; + pdb_set_acct_ctrl( sam_acct, acb_flags, PDB_SET ); + pdb_set_init_flags(sam_acct, PDB_ACCTCTRL, PDB_SET); + } + /** @todo This is where a 're-read on update' should be done */ return sam_acct->methods->update_sam_account(sam_acct->methods, sam_acct); @@ -671,7 +740,7 @@ if (!pdb_context) { return False; } - + return NT_STATUS_IS_OK(pdb_context->pdb_add_sam_account(pdb_context, sam_acct)); } Index: source/utils/pdbedit.c =================================================================== RCS file: /data/cvs/samba/source/utils/pdbedit.c,v retrieving revision 1.87.2.5 diff -u -r1.87.2.5 pdbedit.c --- utils/pdbedit.c 4 Dec 2003 20:35:40 -0000 1.87.2.5 +++ utils/pdbedit.c 5 Feb 2004 14:43:54 -0000 @@ -47,6 +47,7 @@ #define BIT_RESERV_7 0x00800000 #define BIT_IMPORT 0x01000000 #define BIT_EXPORT 0x02000000 +#define BIT_FIX_INIT 0x04000000 #define MASK_ALWAYS_GOOD 0x0000001F #define MASK_USER_GOOD 0x00401F00 @@ -234,6 +235,39 @@ } /********************************************************* + Fix a list of Users for uninitialised passwords +**********************************************************/ +static int fix_users_list (struct pdb_context *in) +{ + SAM_ACCOUNT *sam_pwent=NULL; + BOOL check, ret; + + check = NT_STATUS_IS_OK(in->pdb_setsampwent(in, False)); + if (!check) { + return 1; + } + + check = True; + if (!(NT_STATUS_IS_OK(pdb_init_sam(&sam_pwent)))) return 1; + + while (check && (ret = NT_STATUS_IS_OK(in->pdb_getsampwent (in, sam_pwent)))) { + if (!pdb_update_sam_account(sam_pwent)) { + DEBUG(0, ("Update of user %s failed!\n", pdb_get_username(sam_pwent))); + } + pdb_free_sam(&sam_pwent); + check = NT_STATUS_IS_OK(pdb_init_sam(&sam_pwent)); + if (!check) { + DEBUG(0, ("Failed to initialise new SAM_ACCOUNT structure (out of memory?)\n")); + } + + } + if (check) pdb_free_sam(&sam_pwent); + + in->pdb_endsampwent(in); + return 0; +} + +/********************************************************* Set User Info **********************************************************/ @@ -550,6 +584,7 @@ static char *backend_in = NULL; static char *backend_out = NULL; static BOOL transfer_groups = False; + static BOOL force_initialised_password = False; static char *logon_script = NULL; static char *profile_path = NULL; static char *account_control = NULL; @@ -587,6 +622,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}, + {"force-initialized-passwords", 0, POPT_ARG_NONE, &force_initialised_password, 0, "Force initialization of corrupt password strings in a passdb backend", NULL}, POPT_COMMON_SAMBA POPT_TABLEEND }; @@ -631,6 +667,7 @@ (machine ? BIT_MACHINE : 0) + (user_name ? BIT_USER : 0) + (list_users ? BIT_LIST : 0) + + (force_initialised_password ? BIT_FIX_INIT : 0) + (modify_user ? BIT_MODIFY : 0) + (add_user ? BIT_CREATE : 0) + (delete_user ? BIT_DELETE : 0) + @@ -654,6 +691,10 @@ /* the lowest bit options are always accepted */ checkparms = setparms & ~MASK_ALWAYS_GOOD; + + if (checkparms & BIT_FIX_INIT) { + return fix_users_list(bdef); + } /* account policy operations */ if ((checkparms & BIT_ACCPOLICY) && !(checkparms & ~(BIT_ACCPOLICY + BIT_ACCPOLVAL))) {