1/* 2 Unix SMB/CIFS implementation. 3 struct samu local cache for 4 Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2004. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18*/ 19 20#include "includes.h" 21 22#undef DBGC_CLASS 23#define DBGC_CLASS DBGC_PASSDB 24 25#define LOGIN_CACHE_FILE "login_cache.tdb" 26 27#define SAM_CACHE_FORMAT "dwwd" 28 29static TDB_CONTEXT *cache; 30 31bool login_cache_init(void) 32{ 33 char* cache_fname = NULL; 34 35 /* skip file open if it's already opened */ 36 if (cache) return True; 37 38 cache_fname = cache_path(LOGIN_CACHE_FILE); 39 if (cache_fname == NULL) { 40 DEBUG(0, ("Filename allocation failed.\n")); 41 return False; 42 } 43 44 DEBUG(5, ("Opening cache file at %s\n", cache_fname)); 45 46 cache = tdb_open_log(cache_fname, 0, TDB_DEFAULT, 47 O_RDWR|O_CREAT, 0644); 48 49 if (!cache) 50 DEBUG(5, ("Attempt to open %s failed.\n", cache_fname)); 51 52 TALLOC_FREE(cache_fname); 53 54 return (cache ? True : False); 55} 56 57bool login_cache_shutdown(void) 58{ 59 /* tdb_close routine returns -1 on error */ 60 if (!cache) return False; 61 DEBUG(5, ("Closing cache file\n")); 62 return tdb_close(cache) != -1; 63} 64 65/* if we can't read the cache, oh well, no need to return anything */ 66LOGIN_CACHE * login_cache_read(struct samu *sampass) 67{ 68 char *keystr; 69 TDB_DATA databuf; 70 LOGIN_CACHE *entry; 71 uint32_t entry_timestamp = 0, bad_password_time = 0; 72 uint16_t acct_ctrl; 73 74 if (!login_cache_init()) 75 return NULL; 76 77 if (pdb_get_nt_username(sampass) == NULL) { 78 return NULL; 79 } 80 81 keystr = SMB_STRDUP(pdb_get_nt_username(sampass)); 82 if (!keystr || !keystr[0]) { 83 SAFE_FREE(keystr); 84 return NULL; 85 } 86 87 DEBUG(7, ("Looking up login cache for user %s\n", 88 keystr)); 89 databuf = tdb_fetch_bystring(cache, keystr); 90 SAFE_FREE(keystr); 91 92 if (!(entry = SMB_MALLOC_P(LOGIN_CACHE))) { 93 DEBUG(1, ("Unable to allocate cache entry buffer!\n")); 94 SAFE_FREE(databuf.dptr); 95 return NULL; 96 } 97 ZERO_STRUCTP(entry); 98 99 if (tdb_unpack (databuf.dptr, databuf.dsize, SAM_CACHE_FORMAT, 100 &entry_timestamp, 101 &acct_ctrl, 102 &entry->bad_password_count, 103 &bad_password_time) == -1) { 104 DEBUG(7, ("No cache entry found\n")); 105 SAFE_FREE(entry); 106 SAFE_FREE(databuf.dptr); 107 return NULL; 108 } 109 110 /* 111 * Deal with 32-bit acct_ctrl. In the tdb we only store 16-bit 112 * ("w" in SAM_CACHE_FORMAT). Fixes bug 7253. 113 */ 114 entry->acct_ctrl = acct_ctrl; 115 116 /* Deal with possible 64-bit time_t. */ 117 entry->entry_timestamp = (time_t)entry_timestamp; 118 entry->bad_password_time = (time_t)bad_password_time; 119 120 SAFE_FREE(databuf.dptr); 121 122 DEBUG(5, ("Found login cache entry: timestamp %12u, flags 0x%x, count %d, time %12u\n", 123 (unsigned int)entry->entry_timestamp, entry->acct_ctrl, 124 entry->bad_password_count, (unsigned int)entry->bad_password_time)); 125 return entry; 126} 127 128bool login_cache_write(const struct samu *sampass, LOGIN_CACHE entry) 129{ 130 char *keystr; 131 TDB_DATA databuf; 132 bool ret; 133 uint32_t entry_timestamp; 134 uint32_t bad_password_time = (uint32_t)entry.bad_password_time; 135 136 if (!login_cache_init()) 137 return False; 138 139 if (pdb_get_nt_username(sampass) == NULL) { 140 return False; 141 } 142 143 keystr = SMB_STRDUP(pdb_get_nt_username(sampass)); 144 if (!keystr || !keystr[0]) { 145 SAFE_FREE(keystr); 146 return False; 147 } 148 149 entry_timestamp = (uint32_t)time(NULL); 150 151 databuf.dsize = 152 tdb_pack(NULL, 0, SAM_CACHE_FORMAT, 153 entry_timestamp, 154 entry.acct_ctrl, 155 entry.bad_password_count, 156 bad_password_time); 157 databuf.dptr = SMB_MALLOC_ARRAY(uint8, databuf.dsize); 158 if (!databuf.dptr) { 159 SAFE_FREE(keystr); 160 return False; 161 } 162 163 if (tdb_pack(databuf.dptr, databuf.dsize, SAM_CACHE_FORMAT, 164 entry_timestamp, 165 entry.acct_ctrl, 166 entry.bad_password_count, 167 bad_password_time) 168 != databuf.dsize) { 169 SAFE_FREE(keystr); 170 SAFE_FREE(databuf.dptr); 171 return False; 172 } 173 174 ret = tdb_store_bystring(cache, keystr, databuf, 0); 175 SAFE_FREE(keystr); 176 SAFE_FREE(databuf.dptr); 177 return ret == 0; 178} 179 180bool login_cache_delentry(const struct samu *sampass) 181{ 182 int ret; 183 char *keystr; 184 185 if (!login_cache_init()) 186 return False; 187 188 if (pdb_get_nt_username(sampass) == NULL) { 189 return False; 190 } 191 192 keystr = SMB_STRDUP(pdb_get_nt_username(sampass)); 193 if (!keystr || !keystr[0]) { 194 SAFE_FREE(keystr); 195 return False; 196 } 197 198 DEBUG(9, ("About to delete entry for %s\n", keystr)); 199 ret = tdb_delete_bystring(cache, keystr); 200 DEBUG(9, ("tdb_delete returned %d\n", ret)); 201 202 SAFE_FREE(keystr); 203 return ret == 0; 204} 205