summaryrefslogtreecommitdiff
path: root/source3/passdb/login_cache.c
diff options
context:
space:
mode:
authorJim McDonough <jmcd@samba.org>2004-03-18 19:22:51 +0000
committerJim McDonough <jmcd@samba.org>2004-03-18 19:22:51 +0000
commit357998ddbdeb2fae0a30c578e747154fec22c180 (patch)
treee1d3c687163e603256b60dad9d56333bdc70e5c4 /source3/passdb/login_cache.c
parent5d40499b9f46aff4a70aeda0b8b3b147d2d69c2a (diff)
downloadsamba-357998ddbdeb2fae0a30c578e747154fec22c180.tar.gz
samba-357998ddbdeb2fae0a30c578e747154fec22c180.tar.bz2
samba-357998ddbdeb2fae0a30c578e747154fec22c180.zip
Password lockout for LDAP backend. Caches autolock flag, bad count, and
bad time locally, updating the directory only for hitting the policy limit or resetting. This needed to be done at the passdb level rather than auth, because some of the functions need to be supported from tools such as pdbedit. It was done at the LDAP backend level instead of generically after discussion, because of the complexity of inserting it at a higher level. The login cache read/write/delete is outside of the ldap backend, so it could easily be called by other backends. tdbsam won't call it for obvious reasons, and authors of other backends need to decide if they want to implement it. (This used to be commit 2a679cbc87a2a9111e9e6cdebbb62dec0ab3a0c0)
Diffstat (limited to 'source3/passdb/login_cache.c')
-rw-r--r--source3/passdb/login_cache.c174
1 files changed, 174 insertions, 0 deletions
diff --git a/source3/passdb/login_cache.c b/source3/passdb/login_cache.c
new file mode 100644
index 0000000000..4b760172ec
--- /dev/null
+++ b/source3/passdb/login_cache.c
@@ -0,0 +1,174 @@
+/*
+ Unix SMB/CIFS implementation.
+ SAM_ACCOUNT local cache for
+ Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2004.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_PASSDB
+
+#define LOGIN_CACHE_FILE "login_cache.tdb"
+
+#define SAM_CACHE_FORMAT "dwwd"
+
+static TDB_CONTEXT *cache;
+
+BOOL login_cache_init(void)
+{
+ char* cache_fname = NULL;
+
+ /* skip file open if it's already opened */
+ if (cache) return True;
+
+ asprintf(&cache_fname, "%s/%s", lp_lockdir(), LOGIN_CACHE_FILE);
+ if (cache_fname)
+ DEBUG(5, ("Opening cache file at %s\n", cache_fname));
+ else {
+ DEBUG(0, ("Filename allocation failed.\n"));
+ return False;
+ }
+
+ cache = tdb_open_log(cache_fname, 0, TDB_DEFAULT,
+ O_RDWR|O_CREAT, 0644);
+
+ if (!cache)
+ DEBUG(5, ("Attempt to open %s failed.\n", cache_fname));
+
+ SAFE_FREE(cache_fname);
+
+ return (cache ? True : False);
+}
+
+BOOL login_cache_shutdown(void)
+{
+ /* tdb_close routine returns -1 on error */
+ if (!cache) return False;
+ DEBUG(5, ("Closing cache file\n"));
+ return tdb_close(cache) != -1;
+}
+
+/* if we can't read the cache, oh well, no need to return anything */
+LOGIN_CACHE * login_cache_read(SAM_ACCOUNT *sampass)
+{
+ TDB_DATA keybuf, databuf;
+ LOGIN_CACHE *entry;
+
+ if (!login_cache_init())
+ return NULL;
+
+ keybuf.dptr = strdup(pdb_get_nt_username(sampass));
+ if (!keybuf.dptr || !strlen(keybuf.dptr)) {
+ SAFE_FREE(keybuf.dptr);
+ return NULL;
+ }
+ keybuf.dsize = strlen(keybuf.dptr) + 1;
+
+ DEBUG(7, ("Looking up login cache for user %s\n",
+ keybuf.dptr));
+ databuf = tdb_fetch(cache, keybuf);
+ SAFE_FREE(keybuf.dptr);
+
+ if (!(entry = malloc(sizeof(LOGIN_CACHE)))) {
+ DEBUG(1, ("Unable to allocate cache entry buffer!\n"));
+ SAFE_FREE(databuf.dptr);
+ return NULL;
+ }
+
+ if (tdb_unpack (databuf.dptr, databuf.dsize, SAM_CACHE_FORMAT,
+ &entry->entry_timestamp, &entry->acct_ctrl,
+ &entry->bad_password_count,
+ &entry->bad_password_time) == -1) {
+ DEBUG(7, ("No cache entry found\n"));
+ SAFE_FREE(databuf.dptr);
+ return NULL;
+ }
+
+ DEBUG(5, ("Found login cache entry: timestamp %12u, flags 0x%x, count %d, time %12u\n",
+ entry->entry_timestamp, entry->acct_ctrl,
+ entry->bad_password_count, entry->bad_password_time));
+ return entry;
+}
+
+BOOL login_cache_write(const SAM_ACCOUNT *sampass, LOGIN_CACHE entry)
+{
+
+ TDB_DATA keybuf, databuf;
+ BOOL ret;
+
+
+ keybuf.dptr = strdup(pdb_get_nt_username(sampass));
+ if (!keybuf.dptr || !strlen(keybuf.dptr)) {
+ SAFE_FREE(keybuf.dptr);
+ return False;
+ }
+ keybuf.dsize = strlen(keybuf.dptr) + 1;
+
+ entry.entry_timestamp = time(NULL);
+
+ databuf.dsize =
+ tdb_pack(NULL, 0, SAM_CACHE_FORMAT,
+ entry.entry_timestamp,
+ entry.acct_ctrl,
+ entry.bad_password_count,
+ entry.bad_password_time);
+ databuf.dptr = malloc(databuf.dsize);
+ if (!databuf.dptr) {
+ SAFE_FREE(keybuf.dptr);
+ return False;
+ }
+
+ if (tdb_pack(databuf.dptr, databuf.dsize, SAM_CACHE_FORMAT,
+ entry.entry_timestamp,
+ entry.acct_ctrl,
+ entry.bad_password_count,
+ entry.bad_password_time)
+ != databuf.dsize) {
+ SAFE_FREE(keybuf.dptr);
+ SAFE_FREE(databuf.dptr);
+ return False;
+ }
+
+ ret = tdb_store(cache, keybuf, databuf, 0);
+ SAFE_FREE(keybuf.dptr);
+ SAFE_FREE(databuf.dptr);
+ return ret == 0;
+}
+
+BOOL login_cache_delentry(const SAM_ACCOUNT *sampass)
+{
+ int ret;
+ TDB_DATA keybuf;
+
+ if (!login_cache_init())
+ return False;
+
+ keybuf.dptr = strdup(pdb_get_nt_username(sampass));
+ if (!keybuf.dptr || !strlen(keybuf.dptr)) {
+ SAFE_FREE(keybuf.dptr);
+ return False;
+ }
+ keybuf.dsize = strlen(keybuf.dptr) + 1;
+ DEBUG(9, ("About to delete entry for %s\n", keybuf.dptr));
+ ret = tdb_delete(cache, keybuf);
+ DEBUG(9, ("tdb_delete returned %d\n", ret));
+
+ SAFE_FREE(keybuf.dptr);
+ return ret == 0;
+}
+