source: vendor/current/source3/libsmb/samlogon_cache.c

Last change on this file was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

File size: 7.5 KB
Line 
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.
9
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.
14
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.
19
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/>.
22*/
23
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"
29
30#define NETSAMLOGON_TDB "netsamlogon_cache.tdb"
31
32static TDB_CONTEXT *netsamlogon_tdb = NULL;
33
34/***********************************************************************
35 open the tdb
36 ***********************************************************************/
37
38bool netsamlogon_cache_init(void)
39{
40 bool first_try = true;
41 char *path = NULL;
42 int ret;
43 struct tdb_context *tdb;
44
45 if (netsamlogon_tdb) {
46 return true;
47 }
48
49 path = cache_path(NETSAMLOGON_TDB);
50 if (path == NULL) {
51 return false;
52 }
53again:
54 tdb = tdb_open_log(path, 0, TDB_DEFAULT|TDB_INCOMPATIBLE_HASH,
55 O_RDWR | O_CREAT, 0600);
56 if (tdb == NULL) {
57 DEBUG(0,("tdb_open_log('%s') - failed\n", path));
58 goto clear;
59 }
60
61 ret = tdb_check(tdb, NULL, NULL);
62 if (ret != 0) {
63 tdb_close(tdb);
64 DEBUG(0,("tdb_check('%s') - failed\n", path));
65 goto clear;
66 }
67
68 netsamlogon_tdb = tdb;
69 talloc_free(path);
70 return true;
71
72clear:
73 if (!first_try) {
74 talloc_free(path);
75 return false;
76 }
77 first_try = false;
78
79 DEBUG(0,("retry after truncate for '%s'\n", path));
80 truncate(path, 0);
81 goto again;
82}
83
84
85/***********************************************************************
86 Shutdown samlogon_cache database
87***********************************************************************/
88
89bool netsamlogon_cache_shutdown(void)
90{
91 if (netsamlogon_tdb) {
92 return (tdb_close(netsamlogon_tdb) == 0);
93 }
94
95 return true;
96}
97
98/***********************************************************************
99 Clear cache getpwnam and getgroups entries from the winbindd cache
100***********************************************************************/
101
102void netsamlogon_clear_cached_user(const struct dom_sid *user_sid)
103{
104 fstring keystr;
105
106 if (!netsamlogon_cache_init()) {
107 DEBUG(0,("netsamlogon_clear_cached_user: cannot open "
108 "%s for write!\n",
109 NETSAMLOGON_TDB));
110 return;
111 }
112
113 /* Prepare key as DOMAIN-SID/USER-RID string */
114 sid_to_fstring(keystr, user_sid);
115
116 DEBUG(10,("netsamlogon_clear_cached_user: SID [%s]\n", keystr));
117
118 tdb_delete_bystring(netsamlogon_tdb, keystr);
119}
120
121/***********************************************************************
122 Store a netr_SamInfo3 structure in a tdb for later user
123 username should be in UTF-8 format
124***********************************************************************/
125
126bool netsamlogon_cache_store(const char *username, struct netr_SamInfo3 *info3)
127{
128 TDB_DATA data;
129 fstring keystr;
130 bool result = false;
131 struct dom_sid user_sid;
132 time_t t = time(NULL);
133 TALLOC_CTX *tmp_ctx = talloc_stackframe();
134 DATA_BLOB blob;
135 enum ndr_err_code ndr_err;
136 struct netsamlogoncache_entry r;
137
138 if (!info3) {
139 return false;
140 }
141
142 if (!netsamlogon_cache_init()) {
143 DEBUG(0,("netsamlogon_cache_store: cannot open %s for write!\n",
144 NETSAMLOGON_TDB));
145 return false;
146 }
147
148 sid_compose(&user_sid, info3->base.domain_sid, info3->base.rid);
149
150 /* Prepare key as DOMAIN-SID/USER-RID string */
151 sid_to_fstring(keystr, &user_sid);
152
153 DEBUG(10,("netsamlogon_cache_store: SID [%s]\n", keystr));
154
155 /* Prepare data */
156
157 if (info3->base.full_name.string == NULL) {
158 struct netr_SamInfo3 *cached_info3;
159 const char *full_name = NULL;
160
161 cached_info3 = netsamlogon_cache_get(tmp_ctx, &user_sid);
162 if (cached_info3 != NULL) {
163 full_name = cached_info3->base.full_name.string;
164 }
165
166 if (full_name != NULL) {
167 info3->base.full_name.string = talloc_strdup(info3, full_name);
168 }
169 }
170
171 /* only Samba fills in the username, not sure why NT doesn't */
172 /* so we fill it in since winbindd_getpwnam() makes use of it */
173
174 if (!info3->base.account_name.string) {
175 info3->base.account_name.string = talloc_strdup(info3, username);
176 }
177
178 r.timestamp = t;
179 r.info3 = *info3;
180
181 if (DEBUGLEVEL >= 10) {
182 NDR_PRINT_DEBUG(netsamlogoncache_entry, &r);
183 }
184
185 ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, &r,
186 (ndr_push_flags_fn_t)ndr_push_netsamlogoncache_entry);
187 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
188 DEBUG(0,("netsamlogon_cache_store: failed to push entry to cache\n"));
189 TALLOC_FREE(tmp_ctx);
190 return false;
191 }
192
193 data.dsize = blob.length;
194 data.dptr = blob.data;
195
196 if (tdb_store_bystring(netsamlogon_tdb, keystr, data, TDB_REPLACE) == 0) {
197 result = true;
198 }
199
200 TALLOC_FREE(tmp_ctx);
201
202 return result;
203}
204
205/***********************************************************************
206 Retrieves a netr_SamInfo3 structure from a tdb. Caller must
207 free the user_info struct (malloc()'d memory)
208***********************************************************************/
209
210struct netr_SamInfo3 *netsamlogon_cache_get(TALLOC_CTX *mem_ctx, const struct dom_sid *user_sid)
211{
212 struct netr_SamInfo3 *info3 = NULL;
213 TDB_DATA data;
214 fstring keystr;
215 enum ndr_err_code ndr_err;
216 DATA_BLOB blob;
217 struct netsamlogoncache_entry r;
218
219 if (!netsamlogon_cache_init()) {
220 DEBUG(0,("netsamlogon_cache_get: cannot open %s for write!\n",
221 NETSAMLOGON_TDB));
222 return NULL;
223 }
224
225 /* Prepare key as DOMAIN-SID/USER-RID string */
226 sid_to_fstring(keystr, user_sid);
227 DEBUG(10,("netsamlogon_cache_get: SID [%s]\n", keystr));
228 data = tdb_fetch_bystring( netsamlogon_tdb, keystr );
229
230 if (!data.dptr) {
231 return NULL;
232 }
233
234 info3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
235 if (!info3) {
236 goto done;
237 }
238
239 blob = data_blob_const(data.dptr, data.dsize);
240
241 ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r,
242 (ndr_pull_flags_fn_t)ndr_pull_netsamlogoncache_entry);
243
244 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
245 DEBUG(0,("netsamlogon_cache_get: failed to pull entry from cache\n"));
246 tdb_delete_bystring(netsamlogon_tdb, keystr);
247 TALLOC_FREE(info3);
248 goto done;
249 }
250
251 if (DEBUGLEVEL >= 10) {
252 NDR_PRINT_DEBUG(netsamlogoncache_entry, &r);
253 }
254
255 info3 = (struct netr_SamInfo3 *)talloc_memdup(mem_ctx, &r.info3,
256 sizeof(r.info3));
257
258 done:
259 SAFE_FREE(data.dptr);
260
261 return info3;
262
263#if 0 /* The netsamlogon cache needs to hang around. Something about
264 this feels wrong, but it is the only way we can get all of the
265 groups. The old universal groups cache didn't expire either.
266 --jerry */
267 {
268 time_t now = time(NULL);
269 uint32_t time_diff;
270
271 /* is the entry expired? */
272 time_diff = now - t;
273
274 if ( (time_diff < 0 ) || (time_diff > lp_winbind_cache_time()) ) {
275 DEBUG(10,("netsamlogon_cache_get: cache entry expired \n"));
276 tdb_delete( netsamlogon_tdb, key );
277 TALLOC_FREE( user );
278 }
279 }
280#endif
281}
282
283bool netsamlogon_cache_have(const struct dom_sid *user_sid)
284{
285 TALLOC_CTX *mem_ctx = talloc_init("netsamlogon_cache_have");
286 struct netr_SamInfo3 *info3 = NULL;
287 bool result;
288
289 if (!mem_ctx)
290 return False;
291
292 info3 = netsamlogon_cache_get(mem_ctx, user_sid);
293
294 result = (info3 != NULL);
295
296 talloc_destroy(mem_ctx);
297
298 return result;
299}
Note: See TracBrowser for help on using the repository browser.