diff options
author | Gerald Carter <jerry@samba.org> | 2004-08-06 05:44:26 +0000 |
---|---|---|
committer | Gerald Carter <jerry@samba.org> | 2004-08-06 05:44:26 +0000 |
commit | 547587d57c0ca7fa5babac358d4b2f67a472e142 (patch) | |
tree | abbcd3ba0d6ab0e15317fc0930a3c8e109f322f9 | |
parent | fecd5ea163ffcd1bbee5b06e05112dbff9aa71b1 (diff) | |
download | samba-3.0.6rc2.tar.gz |
r1664: last changes before 3.0.6rc2samba-3.0.6rc2
-rw-r--r-- | WHATSNEW.txt | 133 | ||||
-rw-r--r-- | examples/LDAP/samba.schema | 13 | ||||
-rwxr-xr-x | source/client/mount.cifs.c | 42 | ||||
-rw-r--r-- | source/include/smb.h | 5 | ||||
-rw-r--r-- | source/lib/snprintf.c | 2 | ||||
-rw-r--r-- | source/libsmb/smbencrypt.c | 20 | ||||
-rw-r--r-- | source/nsswitch/winbindd_group.c | 56 | ||||
-rw-r--r-- | source/nsswitch/winbindd_user.c | 8 | ||||
-rw-r--r-- | source/param/loadparm.c | 2 | ||||
-rw-r--r-- | source/passdb/passdb.c | 14 | ||||
-rw-r--r-- | source/passdb/pdb_get_set.c | 37 | ||||
-rw-r--r-- | source/smbd/chgpasswd.c | 20 |
12 files changed, 308 insertions, 44 deletions
diff --git a/WHATSNEW.txt b/WHATSNEW.txt index ea97e56844f..b53ffe549aa 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -1,6 +1,6 @@ ================================ Release Notes for Samba 3.0.6rc2 - Aug 3, 2004 + Aug 5, 2004 ================================ This is a release candidate snapshot of the Samba 3.0.5 code @@ -17,13 +17,38 @@ exact updates. Common bugs fixed in 3.0.6rc2 include: - o + o Fix stalls in smbd caused by inaccessible LDAP servers. + o Remove various memory leaks. + o Fix issues in the password lockout feature. + o Merge security fixes for CAN-2004-0600, CAN-2004-0686 + from 3.0.5. New features introduced in this release include: o Support for maintaining user password history. - +------------------------ +Password History Support +------------------------ + +The new password history feature allows smbd to check the new +password in password change requests against a list of the user's +previous passwords. The number of previous passwords to save can be +set using pdbedit (4 in this example): + + root# pdbedit -P "password history" -C 4 + +When using the ldapsam passdb backend, it is vital to secure +the following attributes from access by non-administrative +users: + + * sambaNTPassword + * sambaLMPassword + * sambaPasswordHistory + +You should refer to your directory server's documentation on how +to implement this restriction). + ###################################################################### Changes ####### @@ -37,6 +62,7 @@ smb.conf changes Parameter Name Action -------------- ------ + ldap timeout New commits @@ -45,9 +71,108 @@ o Jeremy Allison <jra@samba.org> * Add support for storing a user's password history. LDAP portion of the code was based on a patch from Jianliang Lu <j.lu@tiesse.com>. + * Correct memory leaks found in the password change code. + * Fix support for the mknod command with the Linux CIFS client. + * Remove support for passing the new password to smbpasswd + on the command line without using the -s option. + * Ensure home directory service number is correctly reused + (inspired by patches from Michael Collin Nielsen + <michael@hum.aau.dk>). + * Fix to stop printing accounts from resetting the bas + password and account lockout flags. + * If a account was locked out by an admin (and has a bad + password count of zero) leave it locked out until an admin + unlocks it (but log a message). + + +o Tom Alsberg <alsbergt@cs.huji.ac.il> + * Allow pdbedit to export a single user from a passdb backend. + + +o Andrew Bartlett <abartlet@samba.org> + * Improve smbd's internal random number generation. + * Fix a few outstanding long password changes in smbd. + * Fix LANMAN2 session setup code. + + +o Gerald Carter <jerry@samba.org> + * BUG 1520: Work around bug in Windows XP SP2 RC2 where the + client sends a FindNextPrintChangeNotify() request without + previously sending a FindFirstPrintChangeNotify(). Return + the same error code as Windows 2000 SP4. + * BUG 1516: Manually declare ldap_open_with_timeout() to + workaround compiler errors on IRIX (or other systems without + LDAP headers). + * Merge security fixes for CAN-2004-0600, CAN-2004-0686 from + 3.0.5. + * Corrected syntax error in the OID for sambaUnixIdPool, + sambaSidEntry, & sambaIdmapEntry object classes. + + + +o Fabien Chevalier <fabien.chevalier@supelec.fr> + * Debian BUG 252591: Ensure that the return value from the + number of available interfaces is initialized in case no + interfaces are actually available. + + +o Guenther Deschner <gd@sernet.de> + * Display share ACL entries from rpcclient. + + +o Steve French <sfrench@us.ibm.com> + * Fix user unmount of shares mount with suid mount.cifs. + + +o Volker Lendecke <vl@samba.org> + * Allow the 'idmap backend' parameter to accept a list of + LDAP servers for failover purposes. + * Revert code in smbd to remove a tdb when it has become + corrupted. + * Add paranoid checks when mapping SIDs to a uid/gid to + ensure that the type is correct. + * Initial work on getting client support for sending mailslot + datagrams. + * Add 'ldap timeout' parameter. + * Dont always uppercase 'afs username map'. + * Expand aliases for getusersids as well. + + +o James Peach <jpeach@sgi.com> + * More iconv detection fixes for IRIX. + * Compile fixed for systems that do not have C99/UNIX98 compliant + vsnprintf by default. + + +o Tim Potter <tpot@samba.org> + * BUG 1360: Use -Bsymbolic when creating shared libraries to + avoid conflicts with identical symbols in the global namespace + when loading libnss_wins.so. + + +o Richard Renard <rrenard@idealx.com> + * Save the current password as it is being changed into the + password history list. + + +o Simo Source <idra@samba.org> + * Tidy up parametric options in testparm output. + + +o Richard Sharpe <rsharpe@samba.org> + * Add sigchild handling to winbindd to restart the child + daemon if necessary. + + +o Tom Shaw <tomisfaraway@gmail.com> + * Use winbindd_fill_pwent() consistently. + + +o Nick Thompson <nickthompson@agere.com> + * Protect smbd against broken filesystems which return zero + blocksize. - Changes for older versions follow below: -------------------------------------------------- diff --git a/examples/LDAP/samba.schema b/examples/LDAP/samba.schema index 71c954a0c00..d87815b3abc 100644 --- a/examples/LDAP/samba.schema +++ b/examples/LDAP/samba.schema @@ -251,6 +251,11 @@ attributetype ( 1.3.6.1.4.1.7165.2.1.47 NAME 'sambaMungedDial' EQUALITY caseExactMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{1050} ) +attributetype ( 1.3.6.1.4.1.7165.2.1.50 NAME 'sambaPasswordHistory' + DESC 'Concatenated MD4 hashes of the unicode passwords used on this account' + EQUALITY caseIgnoreIA5Match + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{32} ) + ## ## SID, of any type ## @@ -329,7 +334,7 @@ objectclass ( 1.3.6.1.4.1.7165.2.2.6 NAME 'sambaSamAccount' SUP top AUXILIARY displayName $ sambaHomePath $ sambaHomeDrive $ sambaLogonScript $ sambaProfilePath $ description $ sambaUserWorkstations $ sambaPrimaryGroupSID $ sambaDomainName $ sambaMungedDial $ - sambaBadPasswordCount $ sambaBadPasswordTime)) + sambaBadPasswordCount $ sambaBadPasswordTime $ sambaPasswordHistory)) ## ## Group mapping info @@ -350,17 +355,17 @@ objectclass ( 1.3.6.1.4.1.7165.2.2.5 NAME 'sambaDomain' SUP top STRUCTURAL sambaAlgorithmicRidBase ) ) ## used for idmap_ldap module -objectclass ( 1.3.6.1.4.1.7165.1.2.2.7 NAME 'sambaUnixIdPool' SUP top AUXILIARY +objectclass ( 1.3.6.1.4.1.7165.2.2.7 NAME 'sambaUnixIdPool' SUP top AUXILIARY DESC 'Pool for allocating UNIX uids/gids' MUST ( uidNumber $ gidNumber ) ) -objectclass ( 1.3.6.1.4.1.7165.1.2.2.8 NAME 'sambaIdmapEntry' SUP top AUXILIARY +objectclass ( 1.3.6.1.4.1.7165.2.2.8 NAME 'sambaIdmapEntry' SUP top AUXILIARY DESC 'Mapping from a SID to an ID' MUST ( sambaSID ) MAY ( uidNumber $ gidNumber ) ) -objectclass ( 1.3.6.1.4.1.7165.1.2.2.9 NAME 'sambaSidEntry' SUP top STRUCTURAL +objectclass ( 1.3.6.1.4.1.7165.2.2.9 NAME 'sambaSidEntry' SUP top STRUCTURAL DESC 'Structural Class for a SID' MUST ( sambaSID ) ) diff --git a/source/client/mount.cifs.c b/source/client/mount.cifs.c index 5670a147468..55934e04b3c 100755 --- a/source/client/mount.cifs.c +++ b/source/client/mount.cifs.c @@ -38,7 +38,7 @@ #include <fcntl.h> #define MOUNT_CIFS_VERSION_MAJOR "1" -#define MOUNT_CIFS_VERSION_MINOR "3" +#define MOUNT_CIFS_VERSION_MINOR "4" #ifndef MOUNT_CIFS_VENDOR_SUFFIX #define MOUNT_CIFS_VENDOR_SUFFIX "" @@ -57,6 +57,7 @@ static int got_ip = 0; static int got_unc = 0; static int got_uid = 0; static int got_gid = 0; +static int free_share_name = 0; static char * user_name = NULL; char * mountpassword = NULL; @@ -502,8 +503,9 @@ static int parse_options(char * options, int * filesys_flags) } /* Note that caller frees the returned buffer if necessary */ -char * parse_server(char * unc_name) +char * parse_server(char ** punc_name) { + char * unc_name = *punc_name; int length = strnlen(unc_name,1024); char * share; char * ipaddress_string = NULL; @@ -527,11 +529,23 @@ char * parse_server(char * unc_name) return 0; } else { if(strncmp(unc_name,"//",2) && strncmp(unc_name,"\\\\",2)) { - printf("mount error: improperly formatted UNC name."); - printf(" %s does not begin with \\\\ or //\n",unc_name); - return 0; + /* check for nfs syntax ie server:share */ + share = strchr(unc_name,':'); + if(share) { + free_share_name = 1; + *punc_name = malloc(length+3); + *share = '/'; + strncpy((*punc_name)+2,unc_name,length); + unc_name = *punc_name; + unc_name[length+2] = 0; + goto continue_unc_parsing; + } else { + printf("mount error: improperly formatted UNC name."); + printf(" %s does not begin with \\\\ or //\n",unc_name); + return 0; + } } else { - unc_name[0] = '\\'; +continue_unc_parsing: unc_name[0] = '/'; unc_name[1] = '/'; unc_name += 2; @@ -753,8 +767,7 @@ int main(int argc, char ** argv) get_password_from_file(0, getenv("PASSWD_FILE")); } - ipaddr = parse_server(share_name); - + ipaddr = parse_server(&share_name); if(ipaddr == NULL) return -1; @@ -879,8 +892,9 @@ int main(int argc, char ** argv) mountent.mnt_fsname = share_name; mountent.mnt_dir = mountpoint; mountent.mnt_type = "cifs"; - mountent.mnt_opts = malloc(200); + mountent.mnt_opts = malloc(220); if(mountent.mnt_opts) { + char * mount_user = getusername(); memset(mountent.mnt_opts,0,200); if(flags & MS_RDONLY) strcat(mountent.mnt_opts,"ro"); @@ -898,6 +912,13 @@ int main(int argc, char ** argv) strcat(mountent.mnt_opts,",nodev"); if(flags & MS_SYNCHRONOUS) strcat(mountent.mnt_opts,",synch"); + if(mount_user) { + if(getuid() != 0) { + strcat(mountent.mnt_opts,",user="); + strcat(mountent.mnt_opts,mount_user); + } + free(mount_user); + } } mountent.mnt_freq = 0; mountent.mnt_passno = 0; @@ -927,6 +948,9 @@ int main(int argc, char ** argv) free(resolved_path); } + if(free_share_name) { + free(share_name); + } return 0; } diff --git a/source/include/smb.h b/source/include/smb.h index a802e962266..32dba0cf78f 100644 --- a/source/include/smb.h +++ b/source/include/smb.h @@ -625,6 +625,11 @@ typedef struct { #define NT_HASH_LEN 16 #define LM_HASH_LEN 16 +/* Password history contants. */ +#define PW_HISTORY_SALT_LEN 16 +#define SALTED_MD5_HASH_LEN 16 +#define PW_HISTORY_ENTRY_LEN (PW_HISTORY_SALT_LEN+SALTED_MD5_HASH_LEN) + /* * Flags for account policy. */ diff --git a/source/lib/snprintf.c b/source/lib/snprintf.c index 79de3c0ca5d..633517def28 100644 --- a/source/lib/snprintf.c +++ b/source/lib/snprintf.c @@ -821,6 +821,7 @@ static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c) { return dopr(str, count, fmt, args); } +#define vsnprintf smb_vsnprintf #endif /* yes this really must be a ||. Don't muck with this (tridge) @@ -840,6 +841,7 @@ int smb_snprintf(char *str,size_t count,const char *fmt,...) va_end(ap); return ret; } +#define snprintf smb_snprintf #endif #endif diff --git a/source/libsmb/smbencrypt.c b/source/libsmb/smbencrypt.c index 9f936b77aec..d4b05574118 100644 --- a/source/libsmb/smbencrypt.c +++ b/source/libsmb/smbencrypt.c @@ -73,6 +73,26 @@ void E_md4hash(const char *passwd, uchar p16[16]) } /** + * Creates the MD5 Hash of a combination of 16 byte salt and 16 byte NT hash. + * @param 16 byte salt. + * @param 16 byte NT hash. + * @param 16 byte return hashed with md5, caller allocated 16 byte buffer + */ + +void E_md5hash(const uchar salt[16], const uchar nthash[16], uchar hash_out[16]) +{ + struct MD5Context tctx; + uchar array[32]; + + memset(hash_out, '\0', 16); + memcpy(array, salt, 16); + memcpy(&array[16], nthash, 16); + MD5Init(&tctx); + MD5Update(&tctx, array, 32); + MD5Final(hash_out, &tctx); +} + +/** * Creates the DES forward-only Hash of the users password in DOS ASCII charset * @param passwd password in 'unix' charset. * @param p16 return password hashed with DES, caller allocated 16 byte buffer diff --git a/source/nsswitch/winbindd_group.c b/source/nsswitch/winbindd_group.c index 346a2711b6c..ca7f72d0178 100644 --- a/source/nsswitch/winbindd_group.c +++ b/source/nsswitch/winbindd_group.c @@ -1169,6 +1169,48 @@ enum winbindd_result winbindd_getgroups(struct winbindd_cli_state *state) return result; } +static void add_sid_to_array_unique(TALLOC_CTX *mem_ctx, const DOM_SID *sid, + DOM_SID ***sids, int *num_sids) +{ + int i; + + for (i=0; i<(*num_sids); i++) { + if (sid_compare(sid, (*sids)[i]) == 0) + return; + } + + *sids = talloc_realloc(mem_ctx, *sids, sizeof(**sids) * (*num_sids+1)); + + if (*sids == NULL) + return; + + (*sids)[*num_sids] = talloc(mem_ctx, sizeof(DOM_SID)); + sid_copy((*sids)[*num_sids], sid); + *num_sids += 1; + return; +} + +static void add_local_sids_from_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid, + DOM_SID ***user_grpsids, + int *num_groups) +{ + DOM_SID *aliases = NULL; + int i, num_aliases = 0; + + if (!pdb_enum_alias_memberships(sid, &aliases, &num_aliases)) + return; + + if (num_aliases == 0) + return; + + for (i=0; i<num_aliases; i++) + add_sid_to_array_unique(mem_ctx, &aliases[i], user_grpsids, + num_groups); + + SAFE_FREE(aliases); + + return; +} /* Get user supplementary sids. This is equivalent to the winbindd_getgroups() function but it involves a SID->SIDs mapping @@ -1224,6 +1266,20 @@ enum winbindd_result winbindd_getusersids(struct winbindd_cli_state *state) goto no_groups; } + if (lp_winbind_nested_groups()) { + int k; + /* num_groups is changed during the loop, that's why we have + to count down here.*/ + + for (k=num_groups-1; k>=0; k--) { + add_local_sids_from_sid(mem_ctx, user_grpsids[k], + &user_grpsids, &num_groups); + } + + add_local_sids_from_sid(mem_ctx, &user_sid, &user_grpsids, + &num_groups); + } + /* work out the response size */ for (i = 0; i < num_groups; i++) { const char *s = sid_string_static(user_grpsids[i]); diff --git a/source/nsswitch/winbindd_user.c b/source/nsswitch/winbindd_user.c index c691705f9c0..795d657aae7 100644 --- a/source/nsswitch/winbindd_user.c +++ b/source/nsswitch/winbindd_user.c @@ -46,14 +46,14 @@ static BOOL winbindd_fill_pwent(char *dom_name, char *user_name, /* Resolve the uid number */ - if (!NT_STATUS_IS_OK(idmap_sid_to_uid(user_sid, &(pw->pw_uid), 0))) { + if (!NT_STATUS_IS_OK(idmap_sid_to_uid(user_sid, &pw->pw_uid, 0))) { DEBUG(1, ("error getting user id for sid %s\n", sid_to_string(sid_string, user_sid))); return False; } /* Resolve the gid number */ - if (!NT_STATUS_IS_OK(idmap_sid_to_gid(group_sid, &(pw->pw_gid), 0))) { + if (!NT_STATUS_IS_OK(idmap_sid_to_gid(group_sid, &pw->pw_gid, 0))) { DEBUG(1, ("error getting group id for sid %s\n", sid_to_string(sid_string, group_sid))); return False; } @@ -185,7 +185,7 @@ enum winbindd_result winbindd_getpwnam(struct winbindd_cli_state *state) } /* Now take all this information and fill in a passwd structure */ - if (!winbindd_fill_pwent(name_domain, name_user, + if (!winbindd_fill_pwent(name_domain, user_info.acct_name, user_info.user_sid, user_info.group_sid, user_info.full_name, &state->response.data.pw)) { @@ -283,7 +283,7 @@ enum winbindd_result winbindd_getpwuid(struct winbindd_cli_state *state) /* Fill in password structure */ - if (!winbindd_fill_pwent(domain->name, user_name, user_info.user_sid, + if (!winbindd_fill_pwent(domain->name, user_info.acct_name, user_info.user_sid, user_info.group_sid, user_info.full_name, &state->response.data.pw)) { talloc_destroy(mem_ctx); diff --git a/source/param/loadparm.c b/source/param/loadparm.c index 978ea89d5c6..549e232fe07 100644 --- a/source/param/loadparm.c +++ b/source/param/loadparm.c @@ -1120,7 +1120,7 @@ static struct parm_struct parm_table[] = { {"remote browse sync", P_STRING, P_GLOBAL, &Globals.szRemoteBrowseSync, NULL, NULL, FLAG_ADVANCED}, {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL, NULL, FLAG_ADVANCED}, {"homedir map", P_STRING, P_GLOBAL, &Globals.szNISHomeMapName, NULL, NULL, FLAG_ADVANCED}, - {"afs username map", P_USTRING, P_GLOBAL, &Globals.szAfsUsernameMap, NULL, NULL, FLAG_ADVANCED}, + {"afs username map", P_STRING, P_GLOBAL, &Globals.szAfsUsernameMap, NULL, NULL, FLAG_ADVANCED}, {"time offset", P_INTEGER, P_GLOBAL, &extra_time_offset, NULL, NULL, FLAG_ADVANCED}, {"NIS homedir", P_BOOL, P_GLOBAL, &Globals.bNISHomeMap, NULL, NULL, FLAG_ADVANCED}, {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL, NULL, FLAG_HIDE}, diff --git a/source/passdb/passdb.c b/source/passdb/passdb.c index 2f9742e17da..e404f5af3f9 100644 --- a/source/passdb/passdb.c +++ b/source/passdb/passdb.c @@ -1841,18 +1841,20 @@ BOOL init_sam_from_buffer_v2(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); + char *pw_hist = malloc(pwHistLen * PW_HISTORY_ENTRY_LEN); if (!pw_hist) { ret = False; goto done; } - memset(pw_hist, '\0', pwHistLen * NT_HASH_LEN); + memset(pw_hist, '\0', pwHistLen * PW_HISTORY_ENTRY_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; + SMB_ASSERT((nt_pw_hist_len % PW_HISTORY_ENTRY_LEN) == 0); + nt_pw_hist_len /= PW_HISTORY_ENTRY_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); + memcpy(&pw_hist[i*PW_HISTORY_ENTRY_LEN], + &nt_pw_hist_ptr[i*PW_HISTORY_ENTRY_LEN], + PW_HISTORY_ENTRY_LEN); } } if (!pdb_set_pw_history(sampass, pw_hist, pwHistLen, PDB_SET)) { @@ -2048,7 +2050,7 @@ uint32 init_buffer_from_sam_v2 (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL si 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; + nt_pw_hist_len *= PW_HISTORY_ENTRY_LEN; } else { nt_pw_hist_len = 0; } diff --git a/source/passdb/pdb_get_set.c b/source/passdb/pdb_get_set.c index dc8a2f68d21..51c408e6d51 100644 --- a/source/passdb/pdb_get_set.c +++ b/source/passdb/pdb_get_set.c @@ -154,8 +154,8 @@ const uint8* pdb_get_pw_history (const SAM_ACCOUNT *sampass, uint32 *current_his { 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; + || ((sampass->private.nt_pw_his.length % PW_HISTORY_ENTRY_LEN) == 0)); + *current_hist_len = sampass->private.nt_pw_his.length / PW_HISTORY_ENTRY_LEN; return ((uint8*)sampass->private.nt_pw_his.data); } else { *current_hist_len = 0; @@ -995,7 +995,8 @@ 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 + Set the user's password history hash. historyLen is the number of + PW_HISTORY_SALT_LEN+SALTED_MD5_HASH_LEN length entries to store in the history - this must match the size of the uint8 array in pwd. ********************************************************************/ @@ -1006,7 +1007,8 @@ BOOL pdb_set_pw_history (SAM_ACCOUNT *sampass, const uint8 *pwd, uint32 historyL return False; if (historyLen && pwd){ - sampass->private.nt_pw_his = data_blob_talloc(sampass->mem_ctx, pwd, historyLen*NT_HASH_LEN); + sampass->private.nt_pw_his = data_blob_talloc(sampass->mem_ctx, + pwd, historyLen*PW_HISTORY_ENTRY_LEN); if (!sampass->private.nt_pw_his.length) { DEBUG(0, ("pdb_set_pw_history: data_blob_talloc() failed!\n")); return False; @@ -1221,17 +1223,34 @@ BOOL pdb_set_plaintext_passwd (SAM_ACCOUNT *sampass, const char *plaintext) have more history than we need. */ if (current_history_len < pwHistLen) { - /* We only have room for current_history_len entries. */ - pwHistLen = current_history_len; + /* Ensure we have space for the needed history. */ + uchar *new_history = talloc(sampass->mem_ctx, + pwHistLen*PW_HISTORY_ENTRY_LEN); + /* And copy it into the new buffer. */ + if (current_history_len) { + memcpy(new_history, pwhistory, + current_history_len*PW_HISTORY_ENTRY_LEN); + } + /* Clearing out any extra space. */ + memset(&new_history[current_history_len*PW_HISTORY_ENTRY_LEN], + '\0', (pwHistLen-current_history_len)*PW_HISTORY_ENTRY_LEN); + /* Finally replace it. */ + pwhistory = new_history; } } 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 ); + memmove(&pwhistory[PW_HISTORY_ENTRY_LEN], + pwhistory, (pwHistLen -1)*PW_HISTORY_ENTRY_LEN ); } - /* Ensure we have a copy of the new password as the first history entry. */ - memcpy(pwhistory, new_nt_p16, NT_HASH_LEN); + /* Create the new salt as the first part of the history entry. */ + generate_random_buffer(pwhistory, PW_HISTORY_SALT_LEN); + + /* Generate the md5 hash of the salt+new password as the second + part of the history entry. */ + + E_md5hash(pwhistory, new_nt_p16, &pwhistory[PW_HISTORY_SALT_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")); diff --git a/source/smbd/chgpasswd.c b/source/smbd/chgpasswd.c index a1b90c8fed4..5c1d66abc44 100644 --- a/source/smbd/chgpasswd.c +++ b/source/smbd/chgpasswd.c @@ -941,7 +941,7 @@ static NTSTATUS check_oem_password(const char *user, static BOOL check_passwd_history(SAM_ACCOUNT *sampass, const char *plaintext) { uchar new_nt_p16[NT_HASH_LEN]; - uchar zero_nt_pw[NT_HASH_LEN]; + uchar zero_md5_nt_pw[SALTED_MD5_HASH_LEN]; const uint8 *nt_pw; const uint8 *pwhistory; BOOL found = False; @@ -972,22 +972,28 @@ static BOOL check_passwd_history(SAM_ACCOUNT *sampass, const char *plaintext) } dump_data(100, new_nt_p16, NT_HASH_LEN); - dump_data(100, pwhistory, NT_HASH_LEN*pwHisLen); + dump_data(100, pwhistory, PW_HISTORY_ENTRY_LEN*pwHisLen); - memset(zero_nt_pw, '\0', NT_HASH_LEN); + memset(zero_md5_nt_pw, '\0', SALTED_MD5_HASH_LEN); for (i=0; i<pwHisLen; i++) { - if (!memcmp(&pwhistory[i*NT_HASH_LEN], zero_nt_pw, NT_HASH_LEN)) { - /* Ignore zero entries. */ + uchar new_nt_pw_salted_md5_hash[SALTED_MD5_HASH_LEN]; + const uchar *current_salt = &pwhistory[i*PW_HISTORY_ENTRY_LEN]; + const uchar *old_nt_pw_salted_md5_hash = &pwhistory[(i*PW_HISTORY_ENTRY_LEN)+ + PW_HISTORY_SALT_LEN]; + if (!memcmp(zero_md5_nt_pw, old_nt_pw_salted_md5_hash, SALTED_MD5_HASH_LEN)) { + /* Ignore zero valued entries. */ continue; } - if (!memcmp(&pwhistory[i*NT_HASH_LEN], new_nt_p16, NT_HASH_LEN)) { + /* Create salted versions of new to compare. */ + E_md5hash(current_salt, new_nt_p16, new_nt_pw_salted_md5_hash); + + if (!memcmp(new_nt_pw_salted_md5_hash, old_nt_pw_salted_md5_hash, SALTED_MD5_HASH_LEN)) { DEBUG(1,("check_passwd_history: proposed new password for user %s found in history list !\n", pdb_get_username(sampass) )); found = True; break; } } - return found; } |