param: Add errors for when an s3 context is used incorrectly
[Samba.git] / source3 / libsmb / samlogon_cache.c
blob0a157d48463bad8ee290056f979408c0bec50cb4
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 "system/filesys.h"
26 #include "librpc/gen_ndr/ndr_krb5pac.h"
27 #include "../libcli/security/security.h"
28 #include "util_tdb.h"
30 #define NETSAMLOGON_TDB "netsamlogon_cache.tdb"
32 static TDB_CONTEXT *netsamlogon_tdb = NULL;
34 /***********************************************************************
35 open the tdb
36 ***********************************************************************/
38 bool netsamlogon_cache_init(void)
40 bool first_try = true;
41 const char *path = NULL;
42 int ret;
43 struct tdb_context *tdb;
45 if (netsamlogon_tdb) {
46 return true;
49 path = cache_path(NETSAMLOGON_TDB);
50 again:
51 tdb = tdb_open_log(path, 0, TDB_DEFAULT|TDB_INCOMPATIBLE_HASH,
52 O_RDWR | O_CREAT, 0600);
53 if (tdb == NULL) {
54 DEBUG(0,("tdb_open_log('%s') - failed\n", path));
55 goto clear;
58 ret = tdb_check(tdb, NULL, NULL);
59 if (ret != 0) {
60 tdb_close(tdb);
61 DEBUG(0,("tdb_check('%s') - failed\n", path));
62 goto clear;
65 netsamlogon_tdb = tdb;
66 return true;
68 clear:
69 if (!first_try) {
70 return false;
72 first_try = false;
74 DEBUG(0,("retry after truncate for '%s'\n", path));
75 truncate(path, 0);
76 goto again;
80 /***********************************************************************
81 Shutdown samlogon_cache database
82 ***********************************************************************/
84 bool netsamlogon_cache_shutdown(void)
86 if (netsamlogon_tdb) {
87 return (tdb_close(netsamlogon_tdb) == 0);
90 return true;
93 /***********************************************************************
94 Clear cache getpwnam and getgroups entries from the winbindd cache
95 ***********************************************************************/
97 void netsamlogon_clear_cached_user(const struct dom_sid *user_sid)
99 fstring keystr;
101 if (!netsamlogon_cache_init()) {
102 DEBUG(0,("netsamlogon_clear_cached_user: cannot open "
103 "%s for write!\n",
104 NETSAMLOGON_TDB));
105 return;
108 /* Prepare key as DOMAIN-SID/USER-RID string */
109 sid_to_fstring(keystr, user_sid);
111 DEBUG(10,("netsamlogon_clear_cached_user: SID [%s]\n", keystr));
113 tdb_delete_bystring(netsamlogon_tdb, keystr);
116 /***********************************************************************
117 Store a netr_SamInfo3 structure in a tdb for later user
118 username should be in UTF-8 format
119 ***********************************************************************/
121 bool netsamlogon_cache_store(const char *username, struct netr_SamInfo3 *info3)
123 TDB_DATA data;
124 fstring keystr;
125 bool result = false;
126 struct dom_sid user_sid;
127 time_t t = time(NULL);
128 TALLOC_CTX *tmp_ctx = talloc_stackframe();
129 DATA_BLOB blob;
130 enum ndr_err_code ndr_err;
131 struct netsamlogoncache_entry r;
133 if (!info3) {
134 return false;
137 if (!netsamlogon_cache_init()) {
138 DEBUG(0,("netsamlogon_cache_store: cannot open %s for write!\n",
139 NETSAMLOGON_TDB));
140 return false;
143 sid_compose(&user_sid, info3->base.domain_sid, info3->base.rid);
145 /* Prepare key as DOMAIN-SID/USER-RID string */
146 sid_to_fstring(keystr, &user_sid);
148 DEBUG(10,("netsamlogon_cache_store: SID [%s]\n", keystr));
150 /* Prepare data */
152 if (info3->base.full_name.string == NULL) {
153 struct netr_SamInfo3 *cached_info3;
154 const char *full_name = NULL;
156 cached_info3 = netsamlogon_cache_get(tmp_ctx, &user_sid);
157 if (cached_info3 != NULL) {
158 full_name = cached_info3->base.full_name.string;
161 if (full_name != NULL) {
162 info3->base.full_name.string = talloc_strdup(info3, full_name);
166 /* only Samba fills in the username, not sure why NT doesn't */
167 /* so we fill it in since winbindd_getpwnam() makes use of it */
169 if (!info3->base.account_name.string) {
170 info3->base.account_name.string = talloc_strdup(info3, username);
173 r.timestamp = t;
174 r.info3 = *info3;
176 if (DEBUGLEVEL >= 10) {
177 NDR_PRINT_DEBUG(netsamlogoncache_entry, &r);
180 ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, &r,
181 (ndr_push_flags_fn_t)ndr_push_netsamlogoncache_entry);
182 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
183 DEBUG(0,("netsamlogon_cache_store: failed to push entry to cache\n"));
184 TALLOC_FREE(tmp_ctx);
185 return false;
188 data.dsize = blob.length;
189 data.dptr = blob.data;
191 if (tdb_store_bystring(netsamlogon_tdb, keystr, data, TDB_REPLACE) == 0) {
192 result = true;
195 TALLOC_FREE(tmp_ctx);
197 return result;
200 /***********************************************************************
201 Retrieves a netr_SamInfo3 structure from a tdb. Caller must
202 free the user_info struct (malloc()'d memory)
203 ***********************************************************************/
205 struct netr_SamInfo3 *netsamlogon_cache_get(TALLOC_CTX *mem_ctx, const struct dom_sid *user_sid)
207 struct netr_SamInfo3 *info3 = NULL;
208 TDB_DATA data;
209 fstring keystr, tmp;
210 enum ndr_err_code ndr_err;
211 DATA_BLOB blob;
212 struct netsamlogoncache_entry r;
214 if (!netsamlogon_cache_init()) {
215 DEBUG(0,("netsamlogon_cache_get: cannot open %s for write!\n",
216 NETSAMLOGON_TDB));
217 return NULL;
220 /* Prepare key as DOMAIN-SID/USER-RID string */
221 slprintf(keystr, sizeof(keystr), "%s", sid_to_fstring(tmp, user_sid));
222 DEBUG(10,("netsamlogon_cache_get: SID [%s]\n", keystr));
223 data = tdb_fetch_bystring( netsamlogon_tdb, keystr );
225 if (!data.dptr) {
226 return NULL;
229 info3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
230 if (!info3) {
231 goto done;
234 blob = data_blob_const(data.dptr, data.dsize);
236 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
237 (ndr_pull_flags_fn_t)ndr_pull_netsamlogoncache_entry);
239 if (DEBUGLEVEL >= 10) {
240 NDR_PRINT_DEBUG(netsamlogoncache_entry, &r);
243 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
244 DEBUG(0,("netsamlogon_cache_get: failed to pull entry from cache\n"));
245 tdb_delete(netsamlogon_tdb, data);
246 TALLOC_FREE(info3);
247 goto done;
250 info3 = (struct netr_SamInfo3 *)talloc_memdup(mem_ctx, &r.info3,
251 sizeof(r.info3));
253 done:
254 SAFE_FREE(data.dptr);
256 return info3;
258 #if 0 /* The netsamlogon cache needs to hang around. Something about
259 this feels wrong, but it is the only way we can get all of the
260 groups. The old universal groups cache didn't expire either.
261 --jerry */
263 time_t now = time(NULL);
264 uint32 time_diff;
266 /* is the entry expired? */
267 time_diff = now - t;
269 if ( (time_diff < 0 ) || (time_diff > lp_winbind_cache_time()) ) {
270 DEBUG(10,("netsamlogon_cache_get: cache entry expired \n"));
271 tdb_delete( netsamlogon_tdb, key );
272 TALLOC_FREE( user );
275 #endif
278 bool netsamlogon_cache_have(const struct dom_sid *user_sid)
280 TALLOC_CTX *mem_ctx = talloc_init("netsamlogon_cache_have");
281 struct netr_SamInfo3 *info3 = NULL;
282 bool result;
284 if (!mem_ctx)
285 return False;
287 info3 = netsamlogon_cache_get(mem_ctx, user_sid);
289 result = (info3 != NULL);
291 talloc_destroy(mem_ctx);
293 return result;