smbd: Fix CID 240676 Dereference after null check
[samba.git] / source3 / passdb / login_cache.c
index 6ac6d52a63810d6748894116367d00226f087a33..eebb50a8b13f070c68a0083c42f5278a9e5eb858 100644 (file)
@@ -18,6 +18,9 @@
 */
 
 #include "includes.h"
+#include "system/filesys.h"
+#include "passdb.h"
+#include "util_tdb.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_PASSDB
@@ -56,31 +59,32 @@ bool login_cache_init(void)
 
 bool login_cache_shutdown(void)
 {
-       /* tdb_close routine returns -1 on error */
+       /* tdb_close routine returns non-zero on error */
        if (!cache) return False;
        DEBUG(5, ("Closing cache file\n"));
-       return tdb_close(cache) != -1;
+       return tdb_close(cache) == 0;
 }
 
 /* if we can't read the cache, oh well, no need to return anything */
-struct login_cache * login_cache_read(struct samu *sampass)
+bool login_cache_read(struct samu *sampass, struct login_cache *entry)
 {
        char *keystr;
        TDB_DATA databuf;
-       struct login_cache *entry;
        uint32_t entry_timestamp = 0, bad_password_time = 0;
+       uint16_t acct_ctrl;
 
-       if (!login_cache_init())
-               return NULL;
+       if (!login_cache_init()) {
+               return false;
+       }
 
        if (pdb_get_nt_username(sampass) == NULL) {
-               return NULL;
+               return false;
        }
 
        keystr = SMB_STRDUP(pdb_get_nt_username(sampass));
        if (!keystr || !keystr[0]) {
                SAFE_FREE(keystr);
-               return NULL;
+               return false;
        }
 
        DEBUG(7, ("Looking up login cache for user %s\n",
@@ -88,25 +92,24 @@ struct login_cache * login_cache_read(struct samu *sampass)
        databuf = tdb_fetch_bystring(cache, keystr);
        SAFE_FREE(keystr);
 
-       entry = SMB_MALLOC_P(struct login_cache);
-       if (entry == NULL) {
-               DEBUG(1, ("Unable to allocate cache entry buffer!\n"));
-               SAFE_FREE(databuf.dptr);
-               return NULL;
-       }
        ZERO_STRUCTP(entry);
 
        if (tdb_unpack (databuf.dptr, databuf.dsize, SAM_CACHE_FORMAT,
                        &entry_timestamp,
-                       &entry->acct_ctrl,
+                       &acct_ctrl,
                        &entry->bad_password_count,
                        &bad_password_time) == -1) {
                DEBUG(7, ("No cache entry found\n"));
-               SAFE_FREE(entry);
                SAFE_FREE(databuf.dptr);
-               return NULL;
+               return false;
        }
 
+       /*
+        * Deal with 32-bit acct_ctrl. In the tdb we only store 16-bit
+        * ("w" in SAM_CACHE_FORMAT). Fixes bug 7253.
+        */
+       entry->acct_ctrl = acct_ctrl;
+
        /* Deal with possible 64-bit time_t. */
        entry->entry_timestamp = (time_t)entry_timestamp;
        entry->bad_password_time = (time_t)bad_password_time;
@@ -116,16 +119,17 @@ struct login_cache * login_cache_read(struct samu *sampass)
        DEBUG(5, ("Found login cache entry: timestamp %12u, flags 0x%x, count %d, time %12u\n",
                  (unsigned int)entry->entry_timestamp, entry->acct_ctrl, 
                  entry->bad_password_count, (unsigned int)entry->bad_password_time));
-       return entry;
+       return true;
 }
 
-bool login_cache_write(const struct samu *sampass, struct login_cache entry)
+bool login_cache_write(const struct samu *sampass,
+                      const struct login_cache *entry)
 {
        char *keystr;
        TDB_DATA databuf;
        bool ret;
        uint32_t entry_timestamp;
-       uint32_t bad_password_time = (uint32_t)entry.bad_password_time;
+       uint32_t bad_password_time = entry->bad_password_time;
 
        if (!login_cache_init())
                return False;
@@ -145,10 +149,10 @@ bool login_cache_write(const struct samu *sampass, struct login_cache entry)
        databuf.dsize = 
                tdb_pack(NULL, 0, SAM_CACHE_FORMAT,
                         entry_timestamp,
-                        entry.acct_ctrl,
-                        entry.bad_password_count,
+                        entry->acct_ctrl,
+                        entry->bad_password_count,
                         bad_password_time);
-       databuf.dptr = SMB_MALLOC_ARRAY(uint8, databuf.dsize);
+       databuf.dptr = SMB_MALLOC_ARRAY(uint8_t, databuf.dsize);
        if (!databuf.dptr) {
                SAFE_FREE(keystr);
                return False;
@@ -156,8 +160,8 @@ bool login_cache_write(const struct samu *sampass, struct login_cache entry)
 
        if (tdb_pack(databuf.dptr, databuf.dsize, SAM_CACHE_FORMAT,
                         entry_timestamp,
-                        entry.acct_ctrl,
-                        entry.bad_password_count,
+                        entry->acct_ctrl,
+                        entry->bad_password_count,
                         bad_password_time)
            != databuf.dsize) {
                SAFE_FREE(keystr);