summaryrefslogtreecommitdiff
path: root/source3/passdb/pdb_ldap.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/passdb/pdb_ldap.c')
-rw-r--r--source3/passdb/pdb_ldap.c121
1 files changed, 120 insertions, 1 deletions
diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c
index 0ebb63b3fb..b7e28a9e99 100644
--- a/source3/passdb/pdb_ldap.c
+++ b/source3/passdb/pdb_ldap.c
@@ -391,6 +391,25 @@ static BOOL get_unix_attributes (struct ldapsam_privates *ldap_state,
#endif
+static time_t ldapsam_get_entry_timestamp(
+ struct ldapsam_privates *ldap_state,
+ LDAPMessage * entry)
+{
+ pstring temp;
+ struct tm tm;
+
+ 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);
+ tzset();
+ return (mktime(&tm) - timezone);
+}
+
/**********************************************************************
Initialize SAM_ACCOUNT from an LDAP query.
(Based on init_sam_from_buffer in pdb_tdb.c)
@@ -405,7 +424,9 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
kickoff_time,
pass_last_set_time,
pass_can_change_time,
- pass_must_change_time;
+ pass_must_change_time,
+ ldap_entry_time,
+ bad_password_time;
pstring username,
domain,
nt_username,
@@ -427,6 +448,7 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
uint32 hours_len;
uint8 hours[MAX_HOURS_LEN];
pstring temp;
+ LOGIN_CACHE *cache_entry = NULL;
/*
* do a little initialization
@@ -720,6 +742,15 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
pdb_set_bad_password_count(sampass, bad_password_count, PDB_SET);
}
+ if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
+ get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_BAD_PASSWORD_TIME), temp)) {
+ /* leave as default */
+ } else {
+ bad_password_time = (time_t) atol(temp);
+ pdb_set_bad_password_time(sampass, bad_password_time, PDB_SET);
+ }
+
+
if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_LOGON_COUNT), temp)) {
/* leave as default */
@@ -732,6 +763,43 @@ static BOOL init_sam_from_ldap (struct ldapsam_privates *ldap_state,
pdb_set_hours(sampass, hours, PDB_SET);
+ /* check the timestamp of the cache vs ldap entry */
+ if (!(ldap_entry_time = ldapsam_get_entry_timestamp(ldap_state,
+ entry)))
+ return True;
+
+ /* see if we have newer updates */
+ if (!(cache_entry = login_cache_read(sampass))) {
+ DEBUG (9, ("No cache entry, bad count = %d, bad time = %d\n",
+ pdb_get_bad_password_count(sampass),
+ pdb_get_bad_password_time(sampass)));
+ return True;
+ }
+
+ DEBUG(7, ("ldap time is %d, cache time is %d, bad time = %d\n",
+ ldap_entry_time, cache_entry->entry_timestamp,
+ cache_entry->bad_password_time));
+
+ if (ldap_entry_time > cache_entry->entry_timestamp) {
+ /* cache is older than directory , so
+ we need to delete the entry but allow the
+ fields to be written out */
+ login_cache_delentry(sampass);
+ } else {
+ /* read cache in */
+ pdb_set_acct_ctrl(sampass,
+ pdb_get_acct_ctrl(sampass) |
+ (cache_entry->acct_ctrl & ACB_AUTOLOCK),
+ PDB_SET);
+ pdb_set_bad_password_count(sampass,
+ cache_entry->bad_password_count,
+ PDB_SET);
+ pdb_set_bad_password_time(sampass,
+ cache_entry->bad_password_time,
+ PDB_SET);
+ }
+
+ SAFE_FREE(cache_entry);
return True;
}
@@ -907,6 +975,7 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, existing, mods,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_PWD_MUST_CHANGE), temp);
+
if ((pdb_get_acct_ctrl(sampass)&(ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST))
|| (lp_ldap_passwd_sync()!=LDAP_PASSWD_SYNC_ONLY)) {
@@ -954,6 +1023,56 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state,
get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_ACB_INFO),
pdb_encode_acct_ctrl (pdb_get_acct_ctrl(sampass), NEW_PW_FORMAT_SPACE_PADDED_LEN));
+ /* password lockout cache:
+ - If we are now autolocking or clearing, we write to ldap
+ - If we are clearing, we delete the cache entry
+ - If the count is > 0, we update the cache
+
+ This even means when autolocking, we cache, just in case the
+ update doesn't work, and we have to cache the autolock flag */
+
+ if (need_update(sampass, PDB_BAD_PASSWORD_COUNT)) /* &&
+ need_update(sampass, PDB_BAD_PASSWORD_TIME)) */ {
+ uint16 badcount = pdb_get_bad_password_count(sampass);
+ time_t badtime = pdb_get_bad_password_time(sampass);
+ uint32 pol;
+ account_policy_get(AP_BAD_ATTEMPT_LOCKOUT, &pol);
+
+ DEBUG(3, ("updating bad password fields, policy=%d, count=%d, time=%d\n", pol, badcount, badtime));
+
+ if ((badcount >= pol) || (badcount == 0)) {
+ DEBUG(7, ("making mods to update ldap, count=%d, time=%d\n", badcount, badtime));
+ slprintf (temp, sizeof (temp) - 1, "%li", badcount);
+ smbldap_make_mod(
+ ldap_state->smbldap_state->ldap_struct,
+ existing, mods,
+ get_userattr_key2string(
+ ldap_state->schema_ver,
+ LDAP_ATTR_BAD_PASSWORD_COUNT),
+ temp);
+
+ slprintf (temp, sizeof (temp) - 1, "%li", badtime);
+ smbldap_make_mod(
+ ldap_state->smbldap_state->ldap_struct,
+ existing, mods,
+ get_userattr_key2string(
+ ldap_state->schema_ver,
+ LDAP_ATTR_BAD_PASSWORD_TIME),
+ temp);
+ }
+ if (badcount == 0) {
+ DEBUG(7, ("bad password count is reset, deleting login cache entry for %s\n", pdb_get_nt_username(sampass)));
+ login_cache_delentry(sampass);
+ } else {
+ LOGIN_CACHE cache_entry ={time(NULL),
+ pdb_get_acct_ctrl(sampass),
+ badcount, badtime};
+ DEBUG(7, ("Updating bad password count and time in login cache\n"));
+ login_cache_write(sampass, cache_entry);
+ }
+
+ }
+
return True;
}