s3:libsmb: add tstream_is_cli_np()
[Samba/gebeck_regimport.git] / source3 / libsmb / samlogon_cache.c
blob2e7a9c6b031b2270af6fe5e6c0c02b335ccead42
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"
26 #include "../libcli/security/security.h"
28 #define NETSAMLOGON_TDB "netsamlogon_cache.tdb"
30 static TDB_CONTEXT *netsamlogon_tdb = NULL;
32 /***********************************************************************
33 open the tdb
34 ***********************************************************************/
36 bool netsamlogon_cache_init(void)
38 bool first_try = true;
39 const char *path = NULL;
40 int ret;
41 struct tdb_context *tdb;
43 if (netsamlogon_tdb) {
44 return true;
47 path = cache_path(NETSAMLOGON_TDB);
48 again:
49 tdb = tdb_open_log(path, 0, TDB_DEFAULT|TDB_INCOMPATIBLE_HASH,
50 O_RDWR | O_CREAT, 0600);
51 if (tdb == NULL) {
52 DEBUG(0,("tdb_open_log('%s') - failed\n", path));
53 goto clear;
56 ret = tdb_check(tdb, NULL, NULL);
57 if (ret != 0) {
58 tdb_close(tdb);
59 DEBUG(0,("tdb_check('%s') - failed\n", path));
60 goto clear;
63 netsamlogon_tdb = tdb;
64 return true;
66 clear:
67 if (!first_try) {
68 return false;
70 first_try = false;
72 DEBUG(0,("retry after CLEAR_IF_FIRST for '%s'\n", path));
73 tdb = tdb_open_log(path, 0, TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
74 O_RDWR | O_CREAT, 0600);
75 if (tdb) {
76 tdb_close(tdb);
77 goto again;
79 DEBUG(0,("tdb_open_log(%s) with CLEAR_IF_FIRST - failed\n", path));
81 return false;
85 /***********************************************************************
86 Shutdown samlogon_cache database
87 ***********************************************************************/
89 bool netsamlogon_cache_shutdown(void)
91 if (netsamlogon_tdb) {
92 return (tdb_close(netsamlogon_tdb) == 0);
95 return true;
98 /***********************************************************************
99 Clear cache getpwnam and getgroups entries from the winbindd cache
100 ***********************************************************************/
102 void netsamlogon_clear_cached_user(struct netr_SamInfo3 *info3)
104 struct dom_sid user_sid;
105 fstring keystr, tmp;
107 if (!info3) {
108 return;
111 if (!netsamlogon_cache_init()) {
112 DEBUG(0,("netsamlogon_clear_cached_user: cannot open "
113 "%s for write!\n",
114 NETSAMLOGON_TDB));
115 return;
117 sid_compose(&user_sid, info3->base.domain_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 struct 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_compose(&user_sid, info3->base.domain_sid, info3->base.rid);
156 /* Prepare key as DOMAIN-SID/USER-RID string */
157 slprintf(keystr, sizeof(keystr), "%s", sid_to_fstring(tmp, &user_sid));
159 DEBUG(10,("netsamlogon_cache_store: SID [%s]\n", keystr));
161 /* Prepare data */
163 if (!(mem_ctx = TALLOC_P( NULL, int))) {
164 DEBUG(0,("netsamlogon_cache_store: talloc() failed!\n"));
165 return false;
168 /* only Samba fills in the username, not sure why NT doesn't */
169 /* so we fill it in since winbindd_getpwnam() makes use of it */
171 if (!info3->base.account_name.string) {
172 info3->base.account_name.string = talloc_strdup(info3, username);
175 r.timestamp = t;
176 r.info3 = *info3;
178 if (DEBUGLEVEL >= 10) {
179 NDR_PRINT_DEBUG(netsamlogoncache_entry, &r);
182 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &r,
183 (ndr_push_flags_fn_t)ndr_push_netsamlogoncache_entry);
184 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
185 DEBUG(0,("netsamlogon_cache_store: failed to push entry to cache\n"));
186 TALLOC_FREE(mem_ctx);
187 return false;
190 data.dsize = blob.length;
191 data.dptr = blob.data;
193 if (tdb_store_bystring(netsamlogon_tdb, keystr, data, TDB_REPLACE) != -1) {
194 result = true;
197 TALLOC_FREE(mem_ctx);
199 return result;
202 /***********************************************************************
203 Retrieves a netr_SamInfo3 structure from a tdb. Caller must
204 free the user_info struct (malloc()'d memory)
205 ***********************************************************************/
207 struct netr_SamInfo3 *netsamlogon_cache_get(TALLOC_CTX *mem_ctx, const struct dom_sid *user_sid)
209 struct netr_SamInfo3 *info3 = NULL;
210 TDB_DATA data;
211 fstring keystr, tmp;
212 enum ndr_err_code ndr_err;
213 DATA_BLOB blob;
214 struct netsamlogoncache_entry r;
216 if (!netsamlogon_cache_init()) {
217 DEBUG(0,("netsamlogon_cache_get: cannot open %s for write!\n",
218 NETSAMLOGON_TDB));
219 return false;
222 /* Prepare key as DOMAIN-SID/USER-RID string */
223 slprintf(keystr, sizeof(keystr), "%s", sid_to_fstring(tmp, user_sid));
224 DEBUG(10,("netsamlogon_cache_get: SID [%s]\n", keystr));
225 data = tdb_fetch_bystring( netsamlogon_tdb, keystr );
227 if (!data.dptr) {
228 return NULL;
231 info3 = TALLOC_ZERO_P(mem_ctx, struct netr_SamInfo3);
232 if (!info3) {
233 goto done;
236 blob = data_blob_const(data.dptr, data.dsize);
238 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
239 (ndr_pull_flags_fn_t)ndr_pull_netsamlogoncache_entry);
241 if (DEBUGLEVEL >= 10) {
242 NDR_PRINT_DEBUG(netsamlogoncache_entry, &r);
245 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
246 DEBUG(0,("netsamlogon_cache_get: failed to pull entry from cache\n"));
247 tdb_delete(netsamlogon_tdb, data);
248 TALLOC_FREE(info3);
249 goto done;
252 info3 = (struct netr_SamInfo3 *)talloc_memdup(mem_ctx, &r.info3,
253 sizeof(r.info3));
255 done:
256 SAFE_FREE(data.dptr);
258 return info3;
260 #if 0 /* The netsamlogon cache needs to hang around. Something about
261 this feels wrong, but it is the only way we can get all of the
262 groups. The old universal groups cache didn't expire either.
263 --jerry */
265 time_t now = time(NULL);
266 uint32 time_diff;
268 /* is the entry expired? */
269 time_diff = now - t;
271 if ( (time_diff < 0 ) || (time_diff > lp_winbind_cache_time()) ) {
272 DEBUG(10,("netsamlogon_cache_get: cache entry expired \n"));
273 tdb_delete( netsamlogon_tdb, key );
274 TALLOC_FREE( user );
277 #endif
280 bool netsamlogon_cache_have(const struct dom_sid *user_sid)
282 TALLOC_CTX *mem_ctx = talloc_init("netsamlogon_cache_have");
283 struct netr_SamInfo3 *info3 = NULL;
284 bool result;
286 if (!mem_ctx)
287 return False;
289 info3 = netsamlogon_cache_get(mem_ctx, user_sid);
291 result = (info3 != NULL);
293 talloc_destroy(mem_ctx);
295 return result;