summaryrefslogtreecommitdiff
path: root/source3/passdb
diff options
context:
space:
mode:
Diffstat (limited to 'source3/passdb')
-rw-r--r--source3/passdb/pdb_get_set.c90
-rw-r--r--source3/passdb/pdb_ldap.c72
-rw-r--r--source3/passdb/pdb_tdb.c1
3 files changed, 151 insertions, 12 deletions
diff --git a/source3/passdb/pdb_get_set.c b/source3/passdb/pdb_get_set.c
index e69dac524f..4abb951d7b 100644
--- a/source3/passdb/pdb_get_set.c
+++ b/source3/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,20 @@ 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];
+ uchar current_ntpw_copy[NT_HASH_LEN];
+ uchar *current_ntpw = NULL;
if (!sampass || !plaintext)
return False;
-
+
+ /* Store the current password for history purposes. */
+ current_ntpw = (uint8 *)pdb_get_nt_passwd(sampass);
+ if (current_ntpw) {
+ memcpy (current_ntpw_copy, current_ntpw, NT_HASH_LEN);
+ }
+
/* Calculate the MD4 hash (NT compatible) of the password */
E_md4hash(plaintext, new_nt_p16);
@@ -1164,6 +1209,45 @@ 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, &current_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 && current_ntpw && pwHistLen){
+ if (pwHistLen > 1) {
+ memmove(&pwhistory[NT_HASH_LEN], pwhistory, (pwHistLen -1)*NT_HASH_LEN );
+ }
+ memcpy(pwhistory, current_ntpw_copy, 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/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c
index d2ee9a2d9d..fed92cea56 100644
--- a/source3/passdb/pdb_ldap.c
+++ b/source3/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/source3/passdb/pdb_tdb.c b/source3/passdb/pdb_tdb.c
index 9bfb10c400..2cf7c55049 100644
--- a/source3/passdb/pdb_tdb.c
+++ b/source3/passdb/pdb_tdb.c
@@ -746,4 +746,3 @@ NTSTATUS pdb_tdbsam_init(void)
{
return smb_register_passdb(PASSDB_INTERFACE_VERSION, "tdbsam", pdb_init_tdbsam);
}
-