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/>.
25 #include "system/filesys.h"
26 #include "librpc/gen_ndr/ndr_krb5pac.h"
27 #include "../libcli/security/security.h"
30 #define NETSAMLOGON_TDB "netsamlogon_cache.tdb"
32 static TDB_CONTEXT *netsamlogon_tdb = NULL;
34 /***********************************************************************
36 ***********************************************************************/
38 bool netsamlogon_cache_init(void)
40 bool first_try = true;
41 const char *path = NULL;
43 struct tdb_context *tdb;
45 if (netsamlogon_tdb) {
49 path = cache_path(NETSAMLOGON_TDB);
51 tdb = tdb_open_log(path, 0, TDB_DEFAULT|TDB_INCOMPATIBLE_HASH,
52 O_RDWR | O_CREAT, 0600);
54 DEBUG(0,("tdb_open_log('%s') - failed\n", path));
58 ret = tdb_check(tdb, NULL, NULL);
61 DEBUG(0,("tdb_check('%s') - failed\n", path));
65 netsamlogon_tdb = tdb;
74 DEBUG(0,("retry after truncate for '%s'\n", path));
80 /***********************************************************************
81 Shutdown samlogon_cache database
82 ***********************************************************************/
84 bool netsamlogon_cache_shutdown(void)
86 if (netsamlogon_tdb) {
87 return (tdb_close(netsamlogon_tdb) == 0);
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)
101 if (!netsamlogon_cache_init()) {
102 DEBUG(0,("netsamlogon_clear_cached_user: cannot open "
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)
126 struct dom_sid user_sid;
127 time_t t = time(NULL);
128 TALLOC_CTX *tmp_ctx = talloc_stackframe();
130 enum ndr_err_code ndr_err;
131 struct netsamlogoncache_entry r;
137 if (!netsamlogon_cache_init()) {
138 DEBUG(0,("netsamlogon_cache_store: cannot open %s for write!\n",
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));
152 /* only Samba fills in the username, not sure why NT doesn't */
153 /* so we fill it in since winbindd_getpwnam() makes use of it */
155 if (!info3->base.account_name.string) {
156 info3->base.account_name.string = talloc_strdup(info3, username);
162 if (DEBUGLEVEL >= 10) {
163 NDR_PRINT_DEBUG(netsamlogoncache_entry, &r);
166 ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, &r,
167 (ndr_push_flags_fn_t)ndr_push_netsamlogoncache_entry);
168 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
169 DEBUG(0,("netsamlogon_cache_store: failed to push entry to cache\n"));
170 TALLOC_FREE(tmp_ctx);
174 data.dsize = blob.length;
175 data.dptr = blob.data;
177 if (tdb_store_bystring(netsamlogon_tdb, keystr, data, TDB_REPLACE) == 0) {
181 TALLOC_FREE(tmp_ctx);
186 /***********************************************************************
187 Retrieves a netr_SamInfo3 structure from a tdb. Caller must
188 free the user_info struct (malloc()'d memory)
189 ***********************************************************************/
191 struct netr_SamInfo3 *netsamlogon_cache_get(TALLOC_CTX *mem_ctx, const struct dom_sid *user_sid)
193 struct netr_SamInfo3 *info3 = NULL;
196 enum ndr_err_code ndr_err;
198 struct netsamlogoncache_entry r;
200 if (!netsamlogon_cache_init()) {
201 DEBUG(0,("netsamlogon_cache_get: cannot open %s for write!\n",
206 /* Prepare key as DOMAIN-SID/USER-RID string */
207 slprintf(keystr, sizeof(keystr), "%s", sid_to_fstring(tmp, user_sid));
208 DEBUG(10,("netsamlogon_cache_get: SID [%s]\n", keystr));
209 data = tdb_fetch_bystring( netsamlogon_tdb, keystr );
215 info3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
220 blob = data_blob_const(data.dptr, data.dsize);
222 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
223 (ndr_pull_flags_fn_t)ndr_pull_netsamlogoncache_entry);
225 if (DEBUGLEVEL >= 10) {
226 NDR_PRINT_DEBUG(netsamlogoncache_entry, &r);
229 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
230 DEBUG(0,("netsamlogon_cache_get: failed to pull entry from cache\n"));
231 tdb_delete(netsamlogon_tdb, data);
236 info3 = (struct netr_SamInfo3 *)talloc_memdup(mem_ctx, &r.info3,
240 SAFE_FREE(data.dptr);
244 #if 0 /* The netsamlogon cache needs to hang around. Something about
245 this feels wrong, but it is the only way we can get all of the
246 groups. The old universal groups cache didn't expire either.
249 time_t now = time(NULL);
252 /* is the entry expired? */
255 if ( (time_diff < 0 ) || (time_diff > lp_winbind_cache_time()) ) {
256 DEBUG(10,("netsamlogon_cache_get: cache entry expired \n"));
257 tdb_delete( netsamlogon_tdb, key );
264 bool netsamlogon_cache_have(const struct dom_sid *user_sid)
266 TALLOC_CTX *mem_ctx = talloc_init("netsamlogon_cache_have");
267 struct netr_SamInfo3 *info3 = NULL;
273 info3 = netsamlogon_cache_get(mem_ctx, user_sid);
275 result = (info3 != NULL);
277 talloc_destroy(mem_ctx);