diff options
author | Gerald Carter <jerry@samba.org> | 2004-08-04 05:42:36 +0000 |
---|---|---|
committer | Gerald Carter <jerry@samba.org> | 2004-08-04 05:42:36 +0000 |
commit | fecd5ea163ffcd1bbee5b06e05112dbff9aa71b1 (patch) | |
tree | 917402d02525c39dd42d3aed01609ac02be104b4 /source/passdb | |
parent | 7cc5217c98cab4d0d970a2eb7f378319bedb6a46 (diff) | |
download | samba-fecd5ea163ffcd1bbee5b06e05112dbff9aa71b1.tar.gz samba-fecd5ea163ffcd1bbee5b06e05112dbff9aa71b1.tar.xz samba-fecd5ea163ffcd1bbee5b06e05112dbff9aa71b1.zip |
r1643: syncing all changes from 3.0 and hopefully get 3.0.6rc2 out tomorrow
Diffstat (limited to 'source/passdb')
-rw-r--r-- | source/passdb/machine_sid.c | 2 | ||||
-rw-r--r-- | source/passdb/passdb.c | 810 | ||||
-rw-r--r-- | source/passdb/pdb_get_set.c | 84 | ||||
-rw-r--r-- | source/passdb/pdb_ldap.c | 72 | ||||
-rw-r--r-- | source/passdb/pdb_tdb.c | 9 | ||||
-rw-r--r-- | source/passdb/secrets.c | 60 |
6 files changed, 600 insertions, 437 deletions
diff --git a/source/passdb/machine_sid.c b/source/passdb/machine_sid.c index 47b9e2d487e..ce1354ce818 100644 --- a/source/passdb/machine_sid.c +++ b/source/passdb/machine_sid.c @@ -67,7 +67,7 @@ static void generate_random_sid(DOM_SID *sid) sid->num_auths = 0; sid->sub_auths[sid->num_auths++] = 21; - generate_random_buffer(raw_sid_data, 12, True); + generate_random_buffer(raw_sid_data, 12); for (i = 0; i < 3; i++) sid->sub_auths[sid->num_auths++] = IVAL(raw_sid_data, i*4); } diff --git a/source/passdb/passdb.c b/source/passdb/passdb.c index c3a423c2636..2f9742e17da 100644 --- a/source/passdb/passdb.c +++ b/source/passdb/passdb.c @@ -932,7 +932,7 @@ BOOL local_password_change(const char *user_name, int local_flags, if ((local_flags & LOCAL_ADD_USER) || (local_flags & LOCAL_DELETE_USER)) { /* Might not exist in /etc/passwd. Use rid algorithm here */ if (!NT_STATUS_IS_OK(pdb_init_sam_new(&sam_pass, user_name, 0))) { - slprintf(err_str, err_str_len-1, "Failed to initialise SAM_ACCOUNT for user %s.\n", user_name); + slprintf(err_str, err_str_len-1, "Failed to initialise SAM_ACCOUNT for user %s. Does this user exist in the UNIX password database ?\n", user_name); return False; } } else { @@ -1301,6 +1301,7 @@ BOOL local_sid_to_gid(gid_t *pgid, const DOM_SID *psid, enum SID_NAME_USE *name_ #define TDB_FORMAT_STRING_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd" #define TDB_FORMAT_STRING_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd" +#define TDB_FORMAT_STRING_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd" /********************************************************************** Intialize a SAM_ACCOUNT struct from a BYTE buffer of size len @@ -1308,7 +1309,7 @@ BOOL local_sid_to_gid(gid_t *pgid, const DOM_SID *psid, enum SID_NAME_USE *name_ BOOL init_sam_from_buffer(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) { - return(init_sam_from_buffer_v1(sampass, buf, buflen)); + return(init_sam_from_buffer_v2(sampass, buf, buflen)); } /********************************************************************** @@ -1317,7 +1318,7 @@ BOOL init_sam_from_buffer(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) uint32 init_buffer_from_sam (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL size_only) { - return(init_buffer_from_sam_v1(buf, sampass, size_only)); + return(init_buffer_from_sam_v2(buf, sampass, size_only)); } @@ -1354,48 +1355,50 @@ BOOL init_sam_from_buffer_v0(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) uint16 acct_ctrl, logon_divs; uint16 bad_password_count, logon_count; uint8 *hours; - static uint8 *lm_pw_ptr, *nt_pw_ptr; + uint8 *lm_pw_ptr, *nt_pw_ptr; uint32 len = 0; uint32 lm_pw_len, nt_pw_len, hourslen; BOOL ret = True; if(sampass == NULL || buf == NULL) { - DEBUG(0, ("init_sam_from_buffer: NULL parameters found!\n")); + DEBUG(0, ("init_sam_from_buffer_v0: NULL parameters found!\n")); return False; } - + +/* TDB_FORMAT_STRING_V0 "ddddddBBBBBBBBBBBBddBBwdwdBwwd" */ + /* unpack the buffer into variables */ len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V0, - &logon_time, - &logoff_time, - &kickoff_time, - &pass_last_set_time, - &pass_can_change_time, - &pass_must_change_time, - &username_len, &username, - &domain_len, &domain, - &nt_username_len, &nt_username, - &fullname_len, &fullname, - &homedir_len, &homedir, - &dir_drive_len, &dir_drive, - &logon_script_len, &logon_script, - &profile_path_len, &profile_path, - &acct_desc_len, &acct_desc, - &workstations_len, &workstations, - &unknown_str_len, &unknown_str, - &munged_dial_len, &munged_dial, - &user_rid, - &group_rid, - &lm_pw_len, &lm_pw_ptr, - &nt_pw_len, &nt_pw_ptr, - &acct_ctrl, - &remove_me, /* remove on the next TDB_FORMAT upgarde */ - &logon_divs, - &hours_len, - &hourslen, &hours, - &bad_password_count, - &logon_count, - &unknown_6); + &logon_time, /* d */ + &logoff_time, /* d */ + &kickoff_time, /* d */ + &pass_last_set_time, /* d */ + &pass_can_change_time, /* d */ + &pass_must_change_time, /* d */ + &username_len, &username, /* B */ + &domain_len, &domain, /* B */ + &nt_username_len, &nt_username, /* B */ + &fullname_len, &fullname, /* B */ + &homedir_len, &homedir, /* B */ + &dir_drive_len, &dir_drive, /* B */ + &logon_script_len, &logon_script, /* B */ + &profile_path_len, &profile_path, /* B */ + &acct_desc_len, &acct_desc, /* B */ + &workstations_len, &workstations, /* B */ + &unknown_str_len, &unknown_str, /* B */ + &munged_dial_len, &munged_dial, /* B */ + &user_rid, /* d */ + &group_rid, /* d */ + &lm_pw_len, &lm_pw_ptr, /* B */ + &nt_pw_len, &nt_pw_ptr, /* B */ + &acct_ctrl, /* w */ + &remove_me, /* remove on the next TDB_FORMAT upgarde */ /* d */ + &logon_divs, /* w */ + &hours_len, /* d */ + &hourslen, &hours, /* B */ + &bad_password_count, /* w */ + &logon_count, /* w */ + &unknown_6); /* d */ if (len == (uint32) -1) { ret = False; @@ -1465,6 +1468,7 @@ BOOL init_sam_from_buffer_v0(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) } } + pdb_set_pw_history(sampass, NULL, 0, PDB_SET); pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET); pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET); pdb_set_hours_len(sampass, hours_len, PDB_SET); @@ -1489,15 +1493,15 @@ done: SAFE_FREE(workstations); SAFE_FREE(munged_dial); SAFE_FREE(unknown_str); + SAFE_FREE(lm_pw_ptr); + SAFE_FREE(nt_pw_ptr); SAFE_FREE(hours); return ret; } - -uint32 init_buffer_from_sam_v0 (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL size_only) +BOOL init_sam_from_buffer_v1(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) { - size_t len, buflen; /* times are stored as 32bit integer take care on system with 64bit wide time_t @@ -1505,237 +1509,184 @@ uint32 init_buffer_from_sam_v0 (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL si uint32 logon_time, logoff_time, kickoff_time, + bad_password_time, pass_last_set_time, pass_can_change_time, pass_must_change_time; - - uint32 user_rid, group_rid; - - const char *username; - const char *domain; - const char *nt_username; - const char *dir_drive; - const char *unknown_str; - const char *munged_dial; - const char *fullname; - const char *homedir; - const char *logon_script; - const char *profile_path; - const char *acct_desc; - const char *workstations; + char *username; + char *domain; + char *nt_username; + char *dir_drive; + char *unknown_str; + char *munged_dial; + char *fullname; + char *homedir; + char *logon_script; + char *profile_path; + char *acct_desc; + char *workstations; uint32 username_len, domain_len, nt_username_len, dir_drive_len, unknown_str_len, munged_dial_len, fullname_len, homedir_len, logon_script_len, profile_path_len, acct_desc_len, workstations_len; - - const uint8 *lm_pw; - const uint8 *nt_pw; - uint32 lm_pw_len = 16; - uint32 nt_pw_len = 16; - - /* do we have a valid SAM_ACCOUNT pointer? */ - if (sampass == NULL) { - DEBUG(0, ("init_buffer_from_sam: SAM_ACCOUNT is NULL!\n")); - return -1; - } + + uint32 user_rid, group_rid, remove_me, hours_len, unknown_6; + uint16 acct_ctrl, logon_divs; + uint16 bad_password_count, logon_count; + uint8 *hours; + uint8 *lm_pw_ptr, *nt_pw_ptr; + uint32 len = 0; + uint32 lm_pw_len, nt_pw_len, hourslen; + BOOL ret = True; - *buf = NULL; - buflen = 0; + if(sampass == NULL || buf == NULL) { + DEBUG(0, ("init_sam_from_buffer_v1: NULL parameters found!\n")); + return False; + } - logon_time = (uint32)pdb_get_logon_time(sampass); - logoff_time = (uint32)pdb_get_logoff_time(sampass); - kickoff_time = (uint32)pdb_get_kickoff_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); +/* TDB_FORMAT_STRING_V1 "dddddddBBBBBBBBBBBBddBBwdwdBwwd" */ - user_rid = pdb_get_user_rid(sampass); - group_rid = pdb_get_group_rid(sampass); + /* unpack the buffer into variables */ + len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V1, + &logon_time, /* d */ + &logoff_time, /* d */ + &kickoff_time, /* d */ + /* Change from V0 is addition of bad_password_time field. */ + &bad_password_time, /* d */ + &pass_last_set_time, /* d */ + &pass_can_change_time, /* d */ + &pass_must_change_time, /* d */ + &username_len, &username, /* B */ + &domain_len, &domain, /* B */ + &nt_username_len, &nt_username, /* B */ + &fullname_len, &fullname, /* B */ + &homedir_len, &homedir, /* B */ + &dir_drive_len, &dir_drive, /* B */ + &logon_script_len, &logon_script, /* B */ + &profile_path_len, &profile_path, /* B */ + &acct_desc_len, &acct_desc, /* B */ + &workstations_len, &workstations, /* B */ + &unknown_str_len, &unknown_str, /* B */ + &munged_dial_len, &munged_dial, /* B */ + &user_rid, /* d */ + &group_rid, /* d */ + &lm_pw_len, &lm_pw_ptr, /* B */ + &nt_pw_len, &nt_pw_ptr, /* B */ + &acct_ctrl, /* w */ + &remove_me, /* d */ + &logon_divs, /* w */ + &hours_len, /* d */ + &hourslen, &hours, /* B */ + &bad_password_count, /* w */ + &logon_count, /* w */ + &unknown_6); /* d */ + + if (len == (uint32) -1) { + ret = False; + goto done; + } - username = pdb_get_username(sampass); - if (username) - username_len = strlen(username) +1; - else - username_len = 0; + 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); - domain = pdb_get_domain(sampass); - if (domain) - domain_len = strlen(domain) +1; - else - domain_len = 0; + /* Change from V0 is addition of bad_password_time field. */ + pdb_set_bad_password_time(sampass, bad_password_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); - nt_username = pdb_get_nt_username(sampass); - if (nt_username) - nt_username_len = strlen(nt_username) +1; - else - nt_username_len = 0; + pdb_set_username(sampass, username, PDB_SET); + pdb_set_domain(sampass, domain, PDB_SET); + pdb_set_nt_username(sampass, nt_username, PDB_SET); + pdb_set_fullname(sampass, fullname, PDB_SET); - fullname = pdb_get_fullname(sampass); - if (fullname) - fullname_len = strlen(fullname) +1; - else - fullname_len = 0; + if (homedir) { + pdb_set_homedir(sampass, homedir, PDB_SET); + } + else { + pdb_set_homedir(sampass, + talloc_sub_basic(sampass->mem_ctx, username, lp_logon_home()), + PDB_DEFAULT); + } - /* - * Only updates fields which have been set (not defaults from smb.conf) - */ + if (dir_drive) + pdb_set_dir_drive(sampass, dir_drive, PDB_SET); + else { + pdb_set_dir_drive(sampass, + talloc_sub_basic(sampass->mem_ctx, username, lp_logon_drive()), + PDB_DEFAULT); + } - if (!IS_SAM_DEFAULT(sampass, PDB_DRIVE)) - dir_drive = pdb_get_dir_drive(sampass); - else - dir_drive = NULL; - if (dir_drive) - dir_drive_len = strlen(dir_drive) +1; - else - dir_drive_len = 0; + if (logon_script) + pdb_set_logon_script(sampass, logon_script, PDB_SET); + else { + pdb_set_logon_script(sampass, + talloc_sub_basic(sampass->mem_ctx, username, lp_logon_script()), + PDB_DEFAULT); + } + + if (profile_path) { + pdb_set_profile_path(sampass, profile_path, PDB_SET); + } else { + pdb_set_profile_path(sampass, + talloc_sub_basic(sampass->mem_ctx, username, lp_logon_path()), + PDB_DEFAULT); + } - if (!IS_SAM_DEFAULT(sampass, PDB_SMBHOME)) - homedir = pdb_get_homedir(sampass); - else - homedir = NULL; - if (homedir) - homedir_len = strlen(homedir) +1; - else - homedir_len = 0; + pdb_set_acct_desc(sampass, acct_desc, PDB_SET); + pdb_set_workstations(sampass, workstations, PDB_SET); + pdb_set_munged_dial(sampass, munged_dial, PDB_SET); - if (!IS_SAM_DEFAULT(sampass, PDB_LOGONSCRIPT)) - logon_script = pdb_get_logon_script(sampass); - else - logon_script = NULL; - if (logon_script) - logon_script_len = strlen(logon_script) +1; - else - logon_script_len = 0; + if (lm_pw_ptr && lm_pw_len == LM_HASH_LEN) { + if (!pdb_set_lanman_passwd(sampass, lm_pw_ptr, PDB_SET)) { + ret = False; + goto done; + } + } - if (!IS_SAM_DEFAULT(sampass, PDB_PROFILE)) - profile_path = pdb_get_profile_path(sampass); - else - profile_path = NULL; - if (profile_path) - profile_path_len = strlen(profile_path) +1; - else - profile_path_len = 0; - - lm_pw = pdb_get_lanman_passwd(sampass); - if (!lm_pw) - lm_pw_len = 0; - - nt_pw = pdb_get_nt_passwd(sampass); - if (!nt_pw) - nt_pw_len = 0; - - acct_desc = pdb_get_acct_desc(sampass); - if (acct_desc) - acct_desc_len = strlen(acct_desc) +1; - else - acct_desc_len = 0; + if (nt_pw_ptr && nt_pw_len == NT_HASH_LEN) { + if (!pdb_set_nt_passwd(sampass, nt_pw_ptr, PDB_SET)) { + ret = False; + goto done; + } + } - workstations = pdb_get_workstations(sampass); - if (workstations) - workstations_len = strlen(workstations) +1; - else - workstations_len = 0; + pdb_set_pw_history(sampass, NULL, 0, PDB_SET); - unknown_str = NULL; - unknown_str_len = 0; + pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET); + pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET); + pdb_set_hours_len(sampass, hours_len, PDB_SET); + pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET); + pdb_set_logon_count(sampass, logon_count, PDB_SET); + pdb_set_unknown_6(sampass, unknown_6, PDB_SET); + 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); - munged_dial = pdb_get_munged_dial(sampass); - if (munged_dial) - munged_dial_len = strlen(munged_dial) +1; - else - munged_dial_len = 0; - - /* one time to get the size needed */ - len = tdb_pack(NULL, 0, TDB_FORMAT_STRING_V0, - logon_time, - logoff_time, - kickoff_time, - pass_last_set_time, - pass_can_change_time, - pass_must_change_time, - username_len, username, - domain_len, domain, - nt_username_len, nt_username, - fullname_len, fullname, - homedir_len, homedir, - dir_drive_len, dir_drive, - logon_script_len, logon_script, - profile_path_len, profile_path, - acct_desc_len, acct_desc, - workstations_len, workstations, - unknown_str_len, unknown_str, - munged_dial_len, munged_dial, - user_rid, - group_rid, - lm_pw_len, lm_pw, - nt_pw_len, nt_pw, - pdb_get_acct_ctrl(sampass), - 0, /* was: fileds_present, to be removed on format change */ - pdb_get_logon_divs(sampass), - pdb_get_hours_len(sampass), - MAX_HOURS_LEN, pdb_get_hours(sampass), - pdb_get_bad_password_count(sampass), - pdb_get_logon_count(sampass), - pdb_get_unknown_6(sampass)); - - - if (size_only) - return buflen; +done: - /* malloc the space needed */ - if ( (*buf=(uint8*)malloc(len)) == NULL) { - DEBUG(0,("init_buffer_from_sam: Unable to malloc() memory for buffer!\n")); - return (-1); - } - - /* now for the real call to tdb_pack() */ - buflen = tdb_pack((char *)*buf, len, TDB_FORMAT_STRING_V0, - logon_time, - logoff_time, - kickoff_time, - pass_last_set_time, - pass_can_change_time, - pass_must_change_time, - username_len, username, - domain_len, domain, - nt_username_len, nt_username, - fullname_len, fullname, - homedir_len, homedir, - dir_drive_len, dir_drive, - logon_script_len, logon_script, - profile_path_len, profile_path, - acct_desc_len, acct_desc, - workstations_len, workstations, - unknown_str_len, unknown_str, - munged_dial_len, munged_dial, - user_rid, - group_rid, - lm_pw_len, lm_pw, - nt_pw_len, nt_pw, - pdb_get_acct_ctrl(sampass), - 0, /* was: fileds_present, to be removed on format change */ - pdb_get_logon_divs(sampass), - pdb_get_hours_len(sampass), - MAX_HOURS_LEN, pdb_get_hours(sampass), - pdb_get_bad_password_count(sampass), - pdb_get_logon_count(sampass), - pdb_get_unknown_6(sampass)); - - - /* check to make sure we got it correct */ - if (buflen != len) { - DEBUG(0, ("init_buffer_from_sam: somthing odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n", - (unsigned long)buflen, (unsigned long)len)); - /* error */ - SAFE_FREE (*buf); - return (-1); - } + SAFE_FREE(username); + SAFE_FREE(domain); + SAFE_FREE(nt_username); + SAFE_FREE(fullname); + SAFE_FREE(homedir); + SAFE_FREE(dir_drive); + SAFE_FREE(logon_script); + SAFE_FREE(profile_path); + SAFE_FREE(acct_desc); + SAFE_FREE(workstations); + SAFE_FREE(munged_dial); + SAFE_FREE(unknown_str); + SAFE_FREE(lm_pw_ptr); + SAFE_FREE(nt_pw_ptr); + SAFE_FREE(hours); - return (buflen); + return ret; } -BOOL init_sam_from_buffer_v1(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) +BOOL init_sam_from_buffer_v2(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) { /* times are stored as 32bit integer @@ -1765,53 +1716,58 @@ BOOL init_sam_from_buffer_v1(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) fullname_len, homedir_len, logon_script_len, profile_path_len, acct_desc_len, workstations_len; - uint32 user_rid, group_rid, remove_me, hours_len, unknown_6; + uint32 user_rid, group_rid, hours_len, unknown_6; uint16 acct_ctrl, logon_divs; uint16 bad_password_count, logon_count; uint8 *hours; - static uint8 *lm_pw_ptr, *nt_pw_ptr; + uint8 *lm_pw_ptr, *nt_pw_ptr, *nt_pw_hist_ptr; uint32 len = 0; - uint32 lm_pw_len, nt_pw_len, hourslen; + uint32 lm_pw_len, nt_pw_len, nt_pw_hist_len, hourslen; + uint32 pwHistLen = 0; BOOL ret = True; if(sampass == NULL || buf == NULL) { - DEBUG(0, ("init_sam_from_buffer: NULL parameters found!\n")); + DEBUG(0, ("init_sam_from_buffer_v2: NULL parameters found!\n")); return False; } +/* TDB_FORMAT_STRING_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd" */ + /* unpack the buffer into variables */ - len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V1, - &logon_time, - &logoff_time, - &kickoff_time, - &bad_password_time, - &pass_last_set_time, - &pass_can_change_time, - &pass_must_change_time, - &username_len, &username, - &domain_len, &domain, - &nt_username_len, &nt_username, - &fullname_len, &fullname, - &homedir_len, &homedir, - &dir_drive_len, &dir_drive, - &logon_script_len, &logon_script, - &profile_path_len, &profile_path, - &acct_desc_len, &acct_desc, - &workstations_len, &workstations, - &unknown_str_len, &unknown_str, - &munged_dial_len, &munged_dial, - &user_rid, - &group_rid, - &lm_pw_len, &lm_pw_ptr, - &nt_pw_len, &nt_pw_ptr, - &acct_ctrl, - &remove_me, - &logon_divs, - &hours_len, - &hourslen, &hours, - &bad_password_count, - &logon_count, - &unknown_6); + len = tdb_unpack ((char *)buf, buflen, TDB_FORMAT_STRING_V2, + &logon_time, /* d */ + &logoff_time, /* d */ + &kickoff_time, /* d */ + &bad_password_time, /* d */ + &pass_last_set_time, /* d */ + &pass_can_change_time, /* d */ + &pass_must_change_time, /* d */ + &username_len, &username, /* B */ + &domain_len, &domain, /* B */ + &nt_username_len, &nt_username, /* B */ + &fullname_len, &fullname, /* B */ + &homedir_len, &homedir, /* B */ + &dir_drive_len, &dir_drive, /* B */ + &logon_script_len, &logon_script, /* B */ + &profile_path_len, &profile_path, /* B */ + &acct_desc_len, &acct_desc, /* B */ + &workstations_len, &workstations, /* B */ + &unknown_str_len, &unknown_str, /* B */ + &munged_dial_len, &munged_dial, /* B */ + &user_rid, /* d */ + &group_rid, /* d */ + &lm_pw_len, &lm_pw_ptr, /* B */ + &nt_pw_len, &nt_pw_ptr, /* B */ + /* Change from V1 is addition of password history field. */ + &nt_pw_hist_len, &nt_pw_hist_ptr, /* B */ + &acct_ctrl, /* w */ + /* Also "remove_me" field was removed. */ + &logon_divs, /* w */ + &hours_len, /* d */ + &hourslen, &hours, /* B */ + &bad_password_count, /* w */ + &logon_count, /* w */ + &unknown_6); /* d */ if (len == (uint32) -1) { ret = False; @@ -1882,6 +1838,33 @@ BOOL init_sam_from_buffer_v1(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) } } + /* Change from V1 is addition of password history field. */ + account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen); + if (pwHistLen) { + char *pw_hist = malloc(pwHistLen * NT_HASH_LEN); + if (!pw_hist) { + ret = False; + goto done; + } + memset(pw_hist, '\0', pwHistLen * NT_HASH_LEN); + if (nt_pw_hist_ptr && nt_pw_hist_len) { + int i; + SMB_ASSERT((nt_pw_hist_len % NT_HASH_LEN) == 0); + nt_pw_hist_len /= NT_HASH_LEN; + for (i = 0; (i < pwHistLen) && (i < nt_pw_hist_len); i++) { + memcpy(&pw_hist[i*NT_HASH_LEN], &nt_pw_hist_ptr[i*NT_HASH_LEN], NT_HASH_LEN); + } + } + if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) { + SAFE_FREE(pw_hist); + ret = False; + goto done; + } + SAFE_FREE(pw_hist); + } else { + pdb_set_pw_history(sampass, NULL, 0, PDB_SET); + } + pdb_set_user_sid_from_rid(sampass, user_rid, PDB_SET); pdb_set_group_sid_from_rid(sampass, group_rid, PDB_SET); pdb_set_hours_len(sampass, hours_len, PDB_SET); @@ -1906,13 +1889,15 @@ done: SAFE_FREE(workstations); SAFE_FREE(munged_dial); SAFE_FREE(unknown_str); + SAFE_FREE(lm_pw_ptr); + SAFE_FREE(nt_pw_ptr); + SAFE_FREE(nt_pw_hist_ptr); SAFE_FREE(hours); return ret; } - -uint32 init_buffer_from_sam_v1 (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL size_only) +uint32 init_buffer_from_sam_v2 (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL size_only) { size_t len, buflen; @@ -1948,8 +1933,11 @@ uint32 init_buffer_from_sam_v1 (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL si const uint8 *lm_pw; const uint8 *nt_pw; + const uint8 *nt_pw_hist; uint32 lm_pw_len = 16; uint32 nt_pw_len = 16; + uint32 nt_pw_hist_len; + uint32 pwHistLen = 0; /* do we have a valid SAM_ACCOUNT pointer? */ if (sampass == NULL) { @@ -1972,180 +1960,206 @@ uint32 init_buffer_from_sam_v1 (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL si group_rid = pdb_get_group_rid(sampass); username = pdb_get_username(sampass); - if (username) + if (username) { username_len = strlen(username) +1; - else + } else { username_len = 0; + } domain = pdb_get_domain(sampass); - if (domain) + if (domain) { domain_len = strlen(domain) +1; - else + } else { domain_len = 0; + } nt_username = pdb_get_nt_username(sampass); - if (nt_username) + if (nt_username) { nt_username_len = strlen(nt_username) +1; - else + } else { nt_username_len = 0; + } fullname = pdb_get_fullname(sampass); - if (fullname) + if (fullname) { fullname_len = strlen(fullname) +1; - else + } else { fullname_len = 0; + } /* * Only updates fields which have been set (not defaults from smb.conf) */ - if (!IS_SAM_DEFAULT(sampass, PDB_DRIVE)) + if (!IS_SAM_DEFAULT(sampass, PDB_DRIVE)) { dir_drive = pdb_get_dir_drive(sampass); - else + } else { dir_drive = NULL; - if (dir_drive) + } + if (dir_drive) { dir_drive_len = strlen(dir_drive) +1; - else + } else { dir_drive_len = 0; + } - if (!IS_SAM_DEFAULT(sampass, PDB_SMBHOME)) + if (!IS_SAM_DEFAULT(sampass, PDB_SMBHOME)) { homedir = pdb_get_homedir(sampass); - else + } else { homedir = NULL; - if (homedir) + } + if (homedir) { homedir_len = strlen(homedir) +1; - else + } else { homedir_len = 0; + } - if (!IS_SAM_DEFAULT(sampass, PDB_LOGONSCRIPT)) + if (!IS_SAM_DEFAULT(sampass, PDB_LOGONSCRIPT)) { logon_script = pdb_get_logon_script(sampass); - else + } else { logon_script = NULL; - if (logon_script) + } + if (logon_script) { logon_script_len = strlen(logon_script) +1; - else + } else { logon_script_len = 0; + } - if (!IS_SAM_DEFAULT(sampass, PDB_PROFILE)) + if (!IS_SAM_DEFAULT(sampass, PDB_PROFILE)) { profile_path = pdb_get_profile_path(sampass); - else + } else { profile_path = NULL; - if (profile_path) + } + if (profile_path) { profile_path_len = strlen(profile_path) +1; - else + } else { profile_path_len = 0; + } lm_pw = pdb_get_lanman_passwd(sampass); - if (!lm_pw) + if (!lm_pw) { lm_pw_len = 0; + } nt_pw = pdb_get_nt_passwd(sampass); - if (!nt_pw) + if (!nt_pw) { nt_pw_len = 0; - + } + + account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen); + nt_pw_hist = pdb_get_pw_history(sampass, &nt_pw_hist_len); + if (pwHistLen && nt_pw_hist && nt_pw_hist_len) { + nt_pw_hist_len *= NT_HASH_LEN; + } else { + nt_pw_hist_len = 0; + } + acct_desc = pdb_get_acct_desc(sampass); - if (acct_desc) + if (acct_desc) { acct_desc_len = strlen(acct_desc) +1; - else + } else { acct_desc_len = 0; + } workstations = pdb_get_workstations(sampass); - if (workstations) + if (workstations) { workstations_len = strlen(workstations) +1; - else + } else { workstations_len = 0; + } unknown_str = NULL; unknown_str_len = 0; munged_dial = pdb_get_munged_dial(sampass); - if (munged_dial) + if (munged_dial) { munged_dial_len = strlen(munged_dial) +1; - else + } else { munged_dial_len = 0; - + } + +/* TDB_FORMAT_STRING_V2 "dddddddBBBBBBBBBBBBddBBBwwdBwwd" */ + /* one time to get the size needed */ - len = tdb_pack(NULL, 0, TDB_FORMAT_STRING_V1, - logon_time, - logoff_time, - kickoff_time, - bad_password_time, - pass_last_set_time, - pass_can_change_time, - pass_must_change_time, - username_len, username, - domain_len, domain, - nt_username_len, nt_username, - fullname_len, fullname, - homedir_len, homedir, - dir_drive_len, dir_drive, - logon_script_len, logon_script, - profile_path_len, profile_path, - acct_desc_len, acct_desc, - workstations_len, workstations, - unknown_str_len, unknown_str, - munged_dial_len, munged_dial, - user_rid, - group_rid, - lm_pw_len, lm_pw, - nt_pw_len, nt_pw, - pdb_get_acct_ctrl(sampass), - 0, - pdb_get_logon_divs(sampass), - pdb_get_hours_len(sampass), - MAX_HOURS_LEN, pdb_get_hours(sampass), - pdb_get_bad_password_count(sampass), - pdb_get_logon_count(sampass), - pdb_get_unknown_6(sampass)); - - - if (size_only) + len = tdb_pack(NULL, 0, TDB_FORMAT_STRING_V2, + logon_time, /* d */ + logoff_time, /* d */ + kickoff_time, /* d */ + bad_password_time, /* d */ + pass_last_set_time, /* d */ + pass_can_change_time, /* d */ + pass_must_change_time, /* d */ + username_len, username, /* B */ + domain_len, domain, /* B */ + nt_username_len, nt_username, /* B */ + fullname_len, fullname, /* B */ + homedir_len, homedir, /* B */ + dir_drive_len, dir_drive, /* B */ + logon_script_len, logon_script, /* B */ + profile_path_len, profile_path, /* B */ + acct_desc_len, acct_desc, /* B */ + workstations_len, workstations, /* B */ + unknown_str_len, unknown_str, /* B */ + munged_dial_len, munged_dial, /* B */ + user_rid, /* d */ + group_rid, /* d */ + lm_pw_len, lm_pw, /* B */ + nt_pw_len, nt_pw, /* B */ + nt_pw_hist_len, nt_pw_hist, /* B */ + pdb_get_acct_ctrl(sampass), /* w */ + pdb_get_logon_divs(sampass), /* w */ + pdb_get_hours_len(sampass), /* d */ + MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */ + pdb_get_bad_password_count(sampass), /* w */ + pdb_get_logon_count(sampass), /* w */ + pdb_get_unknown_6(sampass)); /* d */ + + if (size_only) { return buflen; + } /* malloc the space needed */ if ( (*buf=(uint8*)malloc(len)) == NULL) { - DEBUG(0,("init_buffer_from_sam: Unable to malloc() memory for buffer!\n")); + DEBUG(0,("init_buffer_from_sam_v2: Unable to malloc() memory for buffer!\n")); return (-1); } /* now for the real call to tdb_pack() */ - buflen = tdb_pack((char *)*buf, len, TDB_FORMAT_STRING_V1, - logon_time, - logoff_time, - kickoff_time, - bad_password_time, - pass_last_set_time, - pass_can_change_time, - pass_must_change_time, - username_len, username, - domain_len, domain, - nt_username_len, nt_username, - fullname_len, fullname, - homedir_len, homedir, - dir_drive_len, dir_drive, - logon_script_len, logon_script, - profile_path_len, profile_path, - acct_desc_len, acct_desc, - workstations_len, workstations, - unknown_str_len, unknown_str, - munged_dial_len, munged_dial, - user_rid, - group_rid, - lm_pw_len, lm_pw, - nt_pw_len, nt_pw, - pdb_get_acct_ctrl(sampass), - 0, - pdb_get_logon_divs(sampass), - pdb_get_hours_len(sampass), - MAX_HOURS_LEN, pdb_get_hours(sampass), - pdb_get_bad_password_count(sampass), - pdb_get_logon_count(sampass), - pdb_get_unknown_6(sampass)); - + buflen = tdb_pack((char *)*buf, len, TDB_FORMAT_STRING_V2, + logon_time, /* d */ + logoff_time, /* d */ + kickoff_time, /* d */ + bad_password_time, /* d */ + pass_last_set_time, /* d */ + pass_can_change_time, /* d */ + pass_must_change_time, /* d */ + username_len, username, /* B */ + domain_len, domain, /* B */ + nt_username_len, nt_username, /* B */ + fullname_len, fullname, /* B */ + homedir_len, homedir, /* B */ + dir_drive_len, dir_drive, /* B */ + logon_script_len, logon_script, /* B */ + profile_path_len, profile_path, /* B */ + acct_desc_len, acct_desc, /* B */ + workstations_len, workstations, /* B */ + unknown_str_len, unknown_str, /* B */ + munged_dial_len, munged_dial, /* B */ + user_rid, /* d */ + group_rid, /* d */ + lm_pw_len, lm_pw, /* B */ + nt_pw_len, nt_pw, /* B */ + nt_pw_hist_len, nt_pw_hist, /* B */ + pdb_get_acct_ctrl(sampass), /* w */ + pdb_get_logon_divs(sampass), /* w */ + pdb_get_hours_len(sampass), /* d */ + MAX_HOURS_LEN, pdb_get_hours(sampass), /* B */ + pdb_get_bad_password_count(sampass), /* w */ + pdb_get_logon_count(sampass), /* w */ + pdb_get_unknown_6(sampass)); /* d */ /* check to make sure we got it correct */ if (buflen != len) { - DEBUG(0, ("init_buffer_from_sam: somthing odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n", + DEBUG(0, ("init_buffer_from_sam_v2: somthing odd is going on here: bufflen (%lu) != len (%lu) in tdb_pack operations!\n", (unsigned long)buflen, (unsigned long)len)); /* error */ SAFE_FREE (*buf); @@ -2155,7 +2169,6 @@ uint32 init_buffer_from_sam_v1 (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL si return (buflen); } - /********************************************************************** **********************************************************************/ @@ -2236,7 +2249,9 @@ BOOL pdb_update_bad_password_count(SAM_ACCOUNT *sampass, BOOL *updated) if (time(NULL) > (LastBadPassword + (time_t)resettime*60)){ pdb_set_bad_password_count(sampass, 0, PDB_CHANGED); pdb_set_bad_password_time(sampass, 0, PDB_CHANGED); - if (updated) *updated = True; + if (updated) { + *updated = True; + } } return True; @@ -2254,7 +2269,8 @@ BOOL pdb_update_autolock_flag(SAM_ACCOUNT *sampass, BOOL *updated) if (!sampass) return False; if (!(pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK)) { - DEBUG(9, ("Account not autolocked, no check needed\n")); + DEBUG(9, ("pdb_update_autolock_flag: Account %s not autolocked, no check needed\n", + pdb_get_username(sampass))); return True; } @@ -2265,20 +2281,30 @@ BOOL pdb_update_autolock_flag(SAM_ACCOUNT *sampass, BOOL *updated) /* First, check if there is a duration to compare */ if ((duration == (uint32) -1) || (duration == 0)) { - DEBUG(9, ("No reset duration, can't reset autolock\n")); + DEBUG(9, ("pdb_update_autolock_flag: No reset duration, can't reset autolock\n")); return True; } LastBadPassword = pdb_get_bad_password_time(sampass); - DEBUG(7, ("LastBadPassword=%d, duration=%d, current time =%d.\n", - (uint32)LastBadPassword, duration*60, (uint32)time(NULL))); + DEBUG(7, ("pdb_update_autolock_flag: Account %s, LastBadPassword=%d, duration=%d, current time =%d.\n", + pdb_get_username(sampass), (uint32)LastBadPassword, duration*60, (uint32)time(NULL))); + + if (LastBadPassword == (time_t)0) { + DEBUG(1,("pdb_update_autolock_flag: Account %s administratively locked out with no \ +bad password time. Leaving locked out.\n", + pdb_get_username(sampass) )); + return True; + } + if ((time(NULL) > (LastBadPassword + (time_t) 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); - if (updated) *updated = True; + if (updated) { + *updated = True; + } } return True; diff --git a/source/passdb/pdb_get_set.c b/source/passdb/pdb_get_set.c index e69dac524f0..dc8a2f68d21 100644 --- a/source/passdb/pdb_get_set.c +++ b/source/passdb/pdb_get_set.c @@ -150,6 +150,19 @@ const uint8* pdb_get_lanman_passwd (const SAM_ACCOUNT *sampass) return (NULL); } +const uint8* pdb_get_pw_history (const SAM_ACCOUNT *sampass, uint32 *current_hist_len) +{ + if (sampass) { + SMB_ASSERT((!sampass->private.nt_pw_his.data) + || ((sampass->private.nt_pw_his.length % NT_HASH_LEN) == 0)); + *current_hist_len = sampass->private.nt_pw_his.length / NT_HASH_LEN; + return ((uint8*)sampass->private.nt_pw_his.data); + } else { + *current_hist_len = 0; + return (NULL); + } +} + /* Return the plaintext password if known. Most of the time it isn't, so don't assume anything magic about this function. @@ -982,6 +995,30 @@ BOOL pdb_set_lanman_passwd (SAM_ACCOUNT *sampass, const uint8 pwd[LM_HASH_LEN], } /********************************************************************* + Set the user's password history hash. historyLen is the number of NT_HASH_LEN + entries to store in the history - this must match the size of the uint8 array + in pwd. +********************************************************************/ + +BOOL pdb_set_pw_history (SAM_ACCOUNT *sampass, const uint8 *pwd, uint32 historyLen, enum pdb_value_state flag) +{ + if (!sampass) + return False; + + if (historyLen && pwd){ + sampass->private.nt_pw_his = data_blob_talloc(sampass->mem_ctx, pwd, historyLen*NT_HASH_LEN); + if (!sampass->private.nt_pw_his.length) { + DEBUG(0, ("pdb_set_pw_history: data_blob_talloc() failed!\n")); + return False; + } + } else { + sampass->private.nt_pw_his = data_blob_talloc(sampass->mem_ctx, NULL, 0); + } + + return pdb_set_init_flags(sampass, PDB_PWHISTORY, flag); +} + +/********************************************************************* Set the user's plaintext password only (base procedure, see helper below) ********************************************************************/ @@ -1133,12 +1170,12 @@ BOOL pdb_set_pass_changed_now (SAM_ACCOUNT *sampass) BOOL pdb_set_plaintext_passwd (SAM_ACCOUNT *sampass, const char *plaintext) { - uchar new_lanman_p16[16]; - uchar new_nt_p16[16]; + uchar new_lanman_p16[LM_HASH_LEN]; + uchar new_nt_p16[NT_HASH_LEN]; if (!sampass || !plaintext) return False; - + /* Calculate the MD4 hash (NT compatible) of the password */ E_md4hash(plaintext, new_nt_p16); @@ -1164,6 +1201,47 @@ BOOL pdb_set_plaintext_passwd (SAM_ACCOUNT *sampass, const char *plaintext) if (!pdb_set_pass_changed_now (sampass)) return False; + /* Store the password history. */ + if (pdb_get_acct_ctrl(sampass) & ACB_NORMAL) { + uchar *pwhistory; + uint32 pwHistLen; + account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen); + if (pwHistLen != 0){ + uint32 current_history_len; + /* We need to make sure we don't have a race condition here - the + account policy history length can change between when the pw_history + was first loaded into the SAM_ACCOUNT struct and now.... JRA. */ + pwhistory = (uchar *)pdb_get_pw_history(sampass, ¤t_history_len); + + if (current_history_len != pwHistLen) { + /* After closing and reopening SAM_ACCOUNT the history + values will sync up. We can't do this here. */ + + /* current_history_len > pwHistLen is not a problem - we + have more history than we need. */ + + if (current_history_len < pwHistLen) { + /* We only have room for current_history_len entries. */ + pwHistLen = current_history_len; + } + } + if (pwhistory && pwHistLen){ + /* Make room for the new password in the history list. */ + if (pwHistLen > 1) { + memmove(&pwhistory[NT_HASH_LEN], pwhistory, (pwHistLen -1)*NT_HASH_LEN ); + } + /* Ensure we have a copy of the new password as the first history entry. */ + memcpy(pwhistory, new_nt_p16, NT_HASH_LEN); + pdb_set_pw_history(sampass, pwhistory, pwHistLen, PDB_CHANGED); + } else { + DEBUG (10,("pdb_get_set.c: pdb_set_plaintext_passwd: pwhistory was NULL!\n")); + } + } else { + /* Set the history length to zero. */ + pdb_set_pw_history(sampass, NULL, 0, PDB_CHANGED); + } + } + return True; } diff --git a/source/passdb/pdb_ldap.c b/source/passdb/pdb_ldap.c index d2ee9a2d9dc..fed92cea568 100644 --- a/source/passdb/pdb_ldap.c +++ b/source/passdb/pdb_ldap.c @@ -81,8 +81,6 @@ #define SAM_ACCOUNT struct sam_passwd #endif -#define MODIFY_TIMESTAMP_STRING "modifyTimestamp" - #include "smbldap.h" struct ldapsam_privates { @@ -301,7 +299,9 @@ static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state, really exist. */ for (attrib = attrs; *attrib != NULL; attrib++) { - if (StrCaseCmp(*attrib, name) == 0) { + if ((StrCaseCmp(*attrib, name) == 0) && + !(StrCaseCmp(*attrib, + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_MOD_TIMESTAMP)))) { DEBUG(10, ("ldapsam_delete_entry: deleting attribute %s\n", name)); smbldap_set_mod(&mods, LDAP_MOD_DELETE, name, NULL); } @@ -400,8 +400,9 @@ static time_t ldapsam_get_entry_timestamp( pstring temp; struct tm tm; - if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, - entry, MODIFY_TIMESTAMP_STRING, temp)) + if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, + get_userattr_key2string(ldap_state->schema_ver,LDAP_ATTR_MOD_TIMESTAMP), + temp)) return (time_t) 0; strptime(temp, "%Y%m%d%H%M%SZ", &tm); @@ -448,6 +449,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, uint8 hours[MAX_HOURS_LEN]; pstring temp; LOGIN_CACHE *cache_entry = NULL; + int pwHistLen; /* * do a little initialization @@ -694,6 +696,37 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, ZERO_STRUCT(smbntpwd); } + account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen); + if (pwHistLen > 0){ + uint8 *pwhist = NULL; + int i; + + if ((pwhist = malloc(NT_HASH_LEN * pwHistLen)) == NULL){ + DEBUG(0, ("init_sam_from_ldap: malloc failed!\n")); + return False; + } + memset(pwhist, '\0', NT_HASH_LEN * pwHistLen); + + if (!smbldap_get_single_pstring (ldap_state->smbldap_state->ldap_struct, entry, + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_HISTORY), temp)) { + /* leave as default - zeros */ + } else { + for (i = 0; i < pwHistLen; i++){ + if (!pdb_gethexpwd(&temp[i*32], smbntpwd)) { + break; + } + memset(&temp[i*32], '\0', 32); + memcpy(&pwhist[i*NT_HASH_LEN], smbntpwd, NT_HASH_LEN); + ZERO_STRUCT(smbntpwd); + } + } + if (!pdb_set_pw_history(sampass, pwhist, pwHistLen, PDB_SET)){ + SAFE_FREE(pwhist); + return False; + } + SAFE_FREE(pwhist); + } + if (!smbldap_get_single_pstring (ldap_state->smbldap_state->ldap_struct, entry, get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ACB_INFO), temp)) { acct_ctrl |= ACB_NORMAL; @@ -781,7 +814,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state, } /********************************************************************** - Initialize SAM_ACCOUNT from an LDAP query. + Initialize the ldap db from a SAM_ACCOUNT. Called on update. (Based on init_buffer_from_sam in pdb_tdb.c) *********************************************************************/ @@ -985,6 +1018,29 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, } } + if (need_update(sampass, PDB_PWHISTORY)) { + int pwHistLen = 0; + account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen); + if (pwHistLen == 0) { + /* Remove any password history from the LDAP store. */ + pstrcpy(temp, "00000000000000000000000000000000"); + } else { + int i, currHistLen = 0; + const uint8 *pwhist = pdb_get_pw_history(sampass, &currHistLen); + if (pwhist != NULL) { + /* We can only store (sizeof(pstring)-1)/32 password history entries. */ + pwHistLen = MIN(pwHistLen, ((sizeof(temp)-1)/32)); + for (i=0; i< pwHistLen && i < currHistLen; i++) { + pdb_sethexpwd (&temp[i*32], &pwhist[i*NT_HASH_LEN], 0); + DEBUG(100, ("temp=%s\n", temp)); + } + } + } + smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, + get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_HISTORY), + temp); + } + if (need_update(sampass, PDB_PASSLASTSET)) { slprintf (temp, sizeof (temp) - 1, "%li", pdb_get_pass_last_set_time(sampass)); smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods, @@ -1162,7 +1218,7 @@ static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT int rc; attr_list = get_userattr_list( ldap_state->schema_ver ); - append_attr(&attr_list, MODIFY_TIMESTAMP_STRING); + append_attr(&attr_list, get_userattr_key2string(ldap_state->schema_ver,LDAP_ATTR_MOD_TIMESTAMP)); rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result, attr_list); free_attr_list( attr_list ); @@ -1208,7 +1264,7 @@ static int ldapsam_get_ldap_user_by_sid(struct ldapsam_privates *ldap_state, switch ( ldap_state->schema_ver ) { case SCHEMAVER_SAMBASAMACCOUNT: attr_list = get_userattr_list(ldap_state->schema_ver); - append_attr(&attr_list, MODIFY_TIMESTAMP_STRING); + append_attr(&attr_list, get_userattr_key2string(ldap_state->schema_ver,LDAP_ATTR_MOD_TIMESTAMP)); rc = ldapsam_search_suffix_by_sid(ldap_state, sid, result, attr_list); free_attr_list( attr_list ); diff --git a/source/passdb/pdb_tdb.c b/source/passdb/pdb_tdb.c index 9bfb10c4009..5fb5ce38913 100644 --- a/source/passdb/pdb_tdb.c +++ b/source/passdb/pdb_tdb.c @@ -37,7 +37,7 @@ static int tdbsam_debug_level = DBGC_ALL; #endif -#define TDBSAM_VERSION 1 /* Most recent TDBSAM version */ +#define TDBSAM_VERSION 2 /* Most recent TDBSAM version */ #define TDBSAM_VERSION_STRING "INFO/version" #define PASSDB_FILE_NAME "passdb.tdb" #define USERPREFIX "USER_" @@ -125,6 +125,9 @@ static BOOL tdbsam_convert(TDB_CONTEXT *pdb_tdb, tdbsamver_t from) case 1: ret = init_sam_from_buffer_v1(user, (uint8 *)data.dptr, data.dsize); break; + case 2: + ret = init_sam_from_buffer_v2(user, (uint8 *)data.dptr, data.dsize); + break; default: /* unknown tdbsam version */ ret = False; @@ -135,6 +138,9 @@ static BOOL tdbsam_convert(TDB_CONTEXT *pdb_tdb, tdbsamver_t from) return False; } + /* We're finished with the old data. */ + SAFE_FREE(data.dptr); + /* pack from the buffer into the new format */ DEBUG(10,("tdbsam_convert: Try packing a record (key:%s) (version:%d)\n", key.dptr, from)); if ((data.dsize=init_buffer_from_sam (&buf, user, False)) == -1) { @@ -746,4 +752,3 @@ NTSTATUS pdb_tdbsam_init(void) { return smb_register_passdb(PASSDB_INTERFACE_VERSION, "tdbsam", pdb_init_tdbsam); } - diff --git a/source/passdb/secrets.c b/source/passdb/secrets.c index 2b3175bed23..e7637f689d2 100644 --- a/source/passdb/secrets.c +++ b/source/passdb/secrets.c @@ -30,10 +30,27 @@ static TDB_CONTEXT *tdb; +/** + * Use a TDB to store an incrementing random seed. + * + * Initialised to the current pid, the very first time Samba starts, + * and incremented by one each time it is needed. + * + * @note Not called by systems with a working /dev/urandom. + */ +static void get_rand_seed(int *new_seed) +{ + *new_seed = sys_getpid(); + if (tdb) { + tdb_change_int32_atomic(tdb, "INFO/random_seed", new_seed, 1); + } +} + /* open up the secrets database */ BOOL secrets_init(void) { pstring fname; + char dummy; if (tdb) return True; @@ -47,6 +64,18 @@ BOOL secrets_init(void) DEBUG(0,("Failed to open %s\n", fname)); return False; } + + /** + * Set a reseed function for the crypto random generator + * + * This avoids a problem where systems without /dev/urandom + * could send the same challenge to multiple clients + */ + set_rand_reseed_callback(get_rand_seed); + + /* Ensure that the reseed is done now, while we are root, etc */ + generate_random_buffer(&dummy, sizeof(dummy)); + return True; } @@ -504,37 +533,6 @@ BOOL trusted_domain_password_delete(const char *domain) } -/******************************************************************* - Reset the 'done' variables so after a client process is created - from a fork call these calls will be re-done. This should be - expanded if more variables need reseting. - ******************************************************************/ - -void reset_globals_after_fork(void) -{ - unsigned char dummy; - - secrets_init(); - - /* - * Increment the global seed value to ensure every smbd starts - * with a new random seed. - */ - - if (tdb) { - uint32 initial_val = sys_getpid(); - tdb_change_int32_atomic(tdb, "INFO/random_seed", (int *)&initial_val, 1); - set_rand_reseed_data((unsigned char *)&initial_val, sizeof(initial_val)); - } - - /* - * Re-seed the random crypto generator, so all smbd's - * started from the same parent won't generate the same - * sequence. - */ - generate_random_buffer( &dummy, 1, True); -} - BOOL secrets_store_ldap_pw(const char* dn, char* pw) { char *key = NULL; |