s3:auth:check_sam_security: introduce a bool var to control pad_pw_count incrementation
[Samba/bb.git] / source3 / libsmb / samlogon_cache.c
blob12901826eee517b8b27992e7eb2989c3514725fd
1 /*
2 Unix SMB/CIFS implementation.
3 Net_sam_logon info3 helpers
4 Copyright (C) Alexander Bokovoy 2002.
5 Copyright (C) Andrew Bartlett 2002.
6 Copyright (C) Gerald Carter 2003.
7 Copyright (C) Tim Potter 2003.
8 Copyright (C) Guenther Deschner 2008.
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
25 #include "librpc/gen_ndr/ndr_krb5pac.h"
27 #define NETSAMLOGON_TDB "netsamlogon_cache.tdb"
29 static TDB_CONTEXT *netsamlogon_tdb = NULL;
31 /***********************************************************************
32 open the tdb
33 ***********************************************************************/
35 bool netsamlogon_cache_init(void)
37 bool first_try = true;
38 const char *path = NULL;
39 int ret;
40 struct tdb_context *tdb;
42 if (netsamlogon_tdb) {
43 return true;
46 path = cache_path(NETSAMLOGON_TDB);
47 again:
48 tdb = tdb_open_log(path, 0, TDB_DEFAULT,
49 O_RDWR | O_CREAT, 0600);
50 if (tdb == NULL) {
51 DEBUG(0,("tdb_open_log('%s') - failed\n", path));
52 goto clear;
55 ret = tdb_check(tdb, NULL, NULL);
56 if (ret != 0) {
57 tdb_close(tdb);
58 DEBUG(0,("tdb_check('%s') - failed\n", path));
59 goto clear;
62 netsamlogon_tdb = tdb;
63 return true;
65 clear:
66 if (!first_try) {
67 return false;
69 first_try = false;
71 DEBUG(0,("retry after CLEAR_IF_FIRST for '%s'\n", path));
72 tdb = tdb_open_log(path, 0, TDB_CLEAR_IF_FIRST,
73 O_RDWR | O_CREAT, 0600);
74 if (tdb) {
75 tdb_close(tdb);
76 goto again;
78 DEBUG(0,("tdb_open_log(%s) with CLEAR_IF_FIRST - failed\n", path));
80 return false;
84 /***********************************************************************
85 Shutdown samlogon_cache database
86 ***********************************************************************/
88 bool netsamlogon_cache_shutdown(void)
90 if (netsamlogon_tdb) {
91 return (tdb_close(netsamlogon_tdb) == 0);
94 return true;
97 /***********************************************************************
98 Clear cache getpwnam and getgroups entries from the winbindd cache
99 ***********************************************************************/
101 void netsamlogon_clear_cached_user(struct netr_SamInfo3 *info3)
103 DOM_SID user_sid;
104 fstring keystr, tmp;
106 if (!info3) {
107 return;
110 if (!netsamlogon_cache_init()) {
111 DEBUG(0,("netsamlogon_clear_cached_user: cannot open "
112 "%s for write!\n",
113 NETSAMLOGON_TDB));
114 return;
116 sid_copy(&user_sid, info3->base.domain_sid);
117 sid_append_rid(&user_sid, info3->base.rid);
119 /* Prepare key as DOMAIN-SID/USER-RID string */
120 slprintf(keystr, sizeof(keystr), "%s", sid_to_fstring(tmp, &user_sid));
122 DEBUG(10,("netsamlogon_clear_cached_user: SID [%s]\n", keystr));
124 tdb_delete_bystring(netsamlogon_tdb, keystr);
127 /***********************************************************************
128 Store a netr_SamInfo3 structure in a tdb for later user
129 username should be in UTF-8 format
130 ***********************************************************************/
132 bool netsamlogon_cache_store(const char *username, struct netr_SamInfo3 *info3)
134 TDB_DATA data;
135 fstring keystr, tmp;
136 bool result = false;
137 DOM_SID user_sid;
138 time_t t = time(NULL);
139 TALLOC_CTX *mem_ctx;
140 DATA_BLOB blob;
141 enum ndr_err_code ndr_err;
142 struct netsamlogoncache_entry r;
144 if (!info3) {
145 return false;
148 if (!netsamlogon_cache_init()) {
149 DEBUG(0,("netsamlogon_cache_store: cannot open %s for write!\n",
150 NETSAMLOGON_TDB));
151 return false;
154 sid_copy(&user_sid, info3->base.domain_sid);
155 sid_append_rid(&user_sid, info3->base.rid);
157 /* Prepare key as DOMAIN-SID/USER-RID string */
158 slprintf(keystr, sizeof(keystr), "%s", sid_to_fstring(tmp, &user_sid));
160 DEBUG(10,("netsamlogon_cache_store: SID [%s]\n", keystr));
162 /* Prepare data */
164 if (!(mem_ctx = TALLOC_P( NULL, int))) {
165 DEBUG(0,("netsamlogon_cache_store: talloc() failed!\n"));
166 return false;
169 /* only Samba fills in the username, not sure why NT doesn't */
170 /* so we fill it in since winbindd_getpwnam() makes use of it */
172 if (!info3->base.account_name.string) {
173 info3->base.account_name.string = talloc_strdup(info3, username);
176 r.timestamp = t;
177 r.info3 = *info3;
179 if (DEBUGLEVEL >= 10) {
180 NDR_PRINT_DEBUG(netsamlogoncache_entry, &r);
183 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &r,
184 (ndr_push_flags_fn_t)ndr_push_netsamlogoncache_entry);
185 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
186 DEBUG(0,("netsamlogon_cache_store: failed to push entry to cache\n"));
187 TALLOC_FREE(mem_ctx);
188 return false;
191 data.dsize = blob.length;
192 data.dptr = blob.data;
194 if (tdb_store_bystring(netsamlogon_tdb, keystr, data, TDB_REPLACE) != -1) {
195 result = true;
198 TALLOC_FREE(mem_ctx);
200 return result;
203 /***********************************************************************
204 Retrieves a netr_SamInfo3 structure from a tdb. Caller must
205 free the user_info struct (malloc()'d memory)
206 ***********************************************************************/
208 struct netr_SamInfo3 *netsamlogon_cache_get(TALLOC_CTX *mem_ctx, const DOM_SID *user_sid)
210 struct netr_SamInfo3 *info3 = NULL;
211 TDB_DATA data;
212 fstring keystr, tmp;
213 enum ndr_err_code ndr_err;
214 DATA_BLOB blob;
215 struct netsamlogoncache_entry r;
217 if (!netsamlogon_cache_init()) {
218 DEBUG(0,("netsamlogon_cache_get: cannot open %s for write!\n",
219 NETSAMLOGON_TDB));
220 return false;
223 /* Prepare key as DOMAIN-SID/USER-RID string */
224 slprintf(keystr, sizeof(keystr), "%s", sid_to_fstring(tmp, user_sid));
225 DEBUG(10,("netsamlogon_cache_get: SID [%s]\n", keystr));
226 data = tdb_fetch_bystring( netsamlogon_tdb, keystr );
228 if (!data.dptr) {
229 return NULL;
232 info3 = TALLOC_ZERO_P(mem_ctx, struct netr_SamInfo3);
233 if (!info3) {
234 goto done;
237 blob = data_blob_const(data.dptr, data.dsize);
239 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, &r,
240 (ndr_pull_flags_fn_t)ndr_pull_netsamlogoncache_entry);
242 if (DEBUGLEVEL >= 10) {
243 NDR_PRINT_DEBUG(netsamlogoncache_entry, &r);
246 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
247 DEBUG(0,("netsamlogon_cache_get: failed to pull entry from cache\n"));
248 tdb_delete(netsamlogon_tdb, data);
249 TALLOC_FREE(info3);
250 goto done;
253 info3 = (struct netr_SamInfo3 *)talloc_memdup(mem_ctx, &r.info3,
254 sizeof(r.info3));
256 done:
257 SAFE_FREE(data.dptr);
259 return info3;
261 #if 0 /* The netsamlogon cache needs to hang around. Something about
262 this feels wrong, but it is the only way we can get all of the
263 groups. The old universal groups cache didn't expire either.
264 --jerry */
266 time_t now = time(NULL);
267 uint32 time_diff;
269 /* is the entry expired? */
270 time_diff = now - t;
272 if ( (time_diff < 0 ) || (time_diff > lp_winbind_cache_time()) ) {
273 DEBUG(10,("netsamlogon_cache_get: cache entry expired \n"));
274 tdb_delete( netsamlogon_tdb, key );
275 TALLOC_FREE( user );
278 #endif
281 bool netsamlogon_cache_have(const DOM_SID *user_sid)
283 TALLOC_CTX *mem_ctx = talloc_init("netsamlogon_cache_have");
284 struct netr_SamInfo3 *info3 = NULL;
285 bool result;
287 if (!mem_ctx)
288 return False;
290 info3 = netsamlogon_cache_get(mem_ctx, user_sid);
292 result = (info3 != NULL);
294 talloc_destroy(mem_ctx);
296 return result;